Definitelytyped: React.Children.map()とReact.cloneElement()の例が必要

作成日 2016年10月26日  ·  8コメント  ·  ソース: DefinitelyTyped/DefinitelyTyped

React.Children.map()良い例がありません、入力方法がわかりません:

/*
<CheckboxGroup ...>
  <Checkbox ... />
  <Checkbox ... />
  <Checkbox ... />
</CheckboxGroup>
*/

// Child
class Checkbox extends React.Component<CheckboxProps, void> {
  // ...
}

// Parent
class CheckboxGroup extends React.Component<CheckboxGroupProps, void> {
  // ...

  render() {
    const checkboxes = React.Children.map(this.props.children, checkbox =>
      React.cloneElement(checkbox, {
        name: this.props.name,
        checked: this.props.checkedValues.includes(checkbox.props.value),
        onChange: this.handleCheckboxChange.bind(this)
      })
    );

    return (
      <div>
        {checkboxes}
      </div>
    );
  }
}

(非常に一般的な例、http://stackoverflow.com/a/32371612/990356を参照)

  • this.props.childrenと入力する方法
  • React.cloneElement()と入力する方法
  • React.Children.map()と入力する方法

ほとんどの場合、次のエラーが発生します: Type 'string' is not assignable to type 'ReactElement<any>' 、#8131を参照

最も参考になるコメント

質問:

const checkboxes = React.Children.map(this.props.children, checkbox =>
  React.cloneElement(checkbox, {
    name: this.props.name,
    checked: this.props.checkedValues.includes(checkbox.props.value),
    onChange: this.handleCheckboxChange.bind(this)
  })
);

解決:

const checkboxes = React.Children.map(props.children, (checkbox: React.ReactElement<CheckboxPropsInternal>) =>
  React.cloneElement(checkbox, {
    checked: props.checkedValues.includes(checkbox.props.value),
    onChange: handleCheckboxChange
  })
);

全てのコメント8件

プルリクエストを送信してください。 確認します。

@vvakameできません、どういう仕組みなのかわかりません

私もです。 定義の作者と会話してください。

this.props.children ReactElement以外の値が含まれていないという保証はないため、 checkbox明示的に型注釈または型アサートする必要があります。 例えば:

React.Children.map(this.props.children, (checkbox: React.ReactElement<CheckboxProps>) => 
    React.cloneElement(checkbox) // should be ok
);

@vsiao thxたくさん、それは動作します!

質問:

const checkboxes = React.Children.map(this.props.children, checkbox =>
  React.cloneElement(checkbox, {
    name: this.props.name,
    checked: this.props.checkedValues.includes(checkbox.props.value),
    onChange: this.handleCheckboxChange.bind(this)
  })
);

解決:

const checkboxes = React.Children.map(props.children, (checkbox: React.ReactElement<CheckboxPropsInternal>) =>
  React.cloneElement(checkbox, {
    checked: props.checkedValues.includes(checkbox.props.value),
    onChange: handleCheckboxChange
  })
);

@tkrotoffあなたもこれを行うことができます:

    React.Children.map(this.props.children, (child: number) => {
      return child + 1
    })

これと提案された解決策は、 React.Children.mapが強く型付けされていないという事実を利用しているだけです。 Checkboxタイプの代わりにany使用した方がよいでしょう。これは、それが子のタイプになるという保証がないためです。 これは、誰かが文字列を渡してコンポーネントを誤って使用すると、ランタイムエラーが発生する可能性が高いことを意味します。

これはどう:

class Slot extends React.PureComponent {
  render () {
    return this.props.children
  }
}

const isReactElement = (obj: {}): obj is React.ReactElement<{}> => {
  return obj.hasOwnProperty('type')
}

const isSlot = (obj: {}): obj is Slot => {
  return isReactElement(obj) && obj.type === Slot
}

const getSlots = (children: React.ReactNode) => React.Children.map(children, (child: React.ReactChild): JSX.Element | null => {
  if (isReactElement(child) && isSlot(child)) {
    return child
  }

  return null
})

class ComponentWithSlots extends React.PureComponent {
  render () {
    const [header, footer] = getSlots(this.props.children)

    return (
      <div>
        {header}
        <div>
          <h1>Welcome</h1>
          <p>This is my lovely component with slots</p>
        </div>
        {footer}
      </div>
    )
  }
}

class MyComponent extends React.PureComponent {
  render () {
    return (
      <ComponentWithSlots>
        <Slot>My Header!</Slot>
        <Slot>
          <div>github: @variousauthors</div>
        </Slot>
      </ComponentWithSlots>
    )
  }
}

レンダリングされます:

My Header!
Welcome
This is my lovely component with slots

github: <strong i="17">@variousauthors</strong>

このアプローチは、私たちが持っている型情報を利用します。つまり、 ReactChildReactElement可能性があります(これを検出するためにtypeを使用しましたが、必要に応じてもっと注意してください)。 Slotよりも説明的で、詳しく説明することもできます。 UIライブラリが、クラスに独自のスロットがアタッチされているパターンを実装しているのを見ました。 何かのようなもの:

<Dropdown>
  <Dropdown.Header>
    <FancyIcon>My Header!</FancyIcon>
  </Dropdown.Header>
  {dropdownItems}
</Dropdown>

このようにして、ユーザーは各スロットの意味を明確に理解できます。 残りの子(スロットとして解析されていないもの)はchildrenというコレクションに残され、ラカートにレンダリングされます。これにより、ユーザーはchildren通常どおり使用しながら、カスタムスロット。

編集:Reactにはどうやら私のカスタムisReactElement代わりに使用できるメソッドReact.isValidElementあります。

編集:他にできることは、コンポーネントにchildrenプロパティを入力することです。これにより、ユーザーはチェックボックスを子としてのみ渡すことができます。 これは、これらのランタイムエラーを回避するのに役立ちます。

このページは役に立ちましたか?
0 / 5 - 0 評価