web-dev-qa-db-ja.com

ReactJs:this.props.childrenにPropTypeはどうあるべきですか?

子をレンダリングする単純なコンポーネントがあるとします。

class ContainerComponent extends Component {
  static propTypes = {
    children: PropTypes.object.isRequired,
  }

  render() {
    return (
      <div>
        {this.props.children}
      </div>
    );
  }
}

export default ContainerComponent;

質問:子供用小道具のpropTypeは何にすべきですか。

オブジェクトとして設定すると、複数の子を持つコンポーネントを使用すると失敗します。

<ContainerComponent>
  <div>1</div>
  <div>2</div>
</ContainerComponent>

Warning:失敗したprop type:無効なprop children型のarrayContainerComponentに提供されました。予想されるobject

配列として設定した場合、1つの子だけを指定すると失敗します。

<ContainerComponent>
  <div>1</div>
</ContainerComponent>

Warning:失敗したprop型:ContainerComponentに渡されたobject型の無効なprop子、期待される配列。

アドバイスしてください、私は子供の要素のためにpropTypesのチェックをするのを邪魔してはいけないのですか?

166
d3ming

oneOfTypeまたはPropTypes.nodeを利用して、このようなことを試してください。

import PropTypes from 'prop-types'

...

static propTypes = {
    children: PropTypes.oneOfType([
        PropTypes.arrayOf(PropTypes.node),
        PropTypes.node
    ]).isRequired
}

または

static propTypes = {
    children: PropTypes.node.isRequired,
}
238

私にとっては、コンポーネントによって異なります。必要なものがわかっている場合は、次のようにして排他的に、または複数の型を指定するようにしてください。

PropTypes.oneOfType 

しかし、私はほとんどの場合、多くの種類の子を持つことができるより一般的なコンポーネントを使用して、私は使用して嬉しいです

PropTypes.any

Reactコンポーネントを参照したいのなら、あなたは探しているでしょう。

PropTypes.element

が、

PropTypes.node

文字列、数値、要素、またはこれらのものの配列など、レンダリングできるものすべてを記述します。これがあなたに合っているなら、これは方法です。

21
ggilberth

PropTypesドキュメント には以下があります。

// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
optionalNode: PropTypes.node,

そのため、PropTypes.nodeを使用して、オブジェクトまたはオブジェクトの配列を確認できます。

static propTypes = {
   children: PropTypes.node.isRequired,
}
6
DC.Azndj

ここでの答えは正確に子供たちをチェックすることをカバーしていないようです。 nodeobjectは寛容すぎるので、正確な要素をチェックしたいと思いました。これが私が使用したものです:

  • oneOfType([])を使用して、単一または複数の子を許可します
  • 単一の子配列にshapeを使用し、子の配列にarrayOf(shape({}))を使用します。
  • 子要素自体にoneOfを使用する

最後に、このようなもの:

import PropTypes from 'prop-types'
import MyComponent from './MyComponent'

children: PropTypes.oneOfType([
  PropTypes.shape({
    type: PropTypes.oneOf([MyComponent]),
  }),
  PropTypes.arrayOf(
    PropTypes.shape({
      type: PropTypes.oneOf([MyComponent]),
    })
  ),
]).isRequired

この問題は私がこれをより明確に理解するのを助けました: https://github.com/facebook/react/issues/2979

4
d3vkit

コンポーネントの種類と正確に一致させたい場合は、これをチェックしてください。

MenuPrimary.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(MenuPrimaryItem),
    PropTypes.objectOf(MenuPrimaryItem)
  ])
}

いくつかのコンポーネントタイプを正確に一致させたい場合は、これをチェックしてください。

const HeaderTypes = [
  PropTypes.objectOf(MenuPrimary),
  PropTypes.objectOf(UserInfo)
]

Header.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.oneOfType([...HeaderTypes])),
    ...HeaderTypes
  ])
}
2
Andrew Luca

カスタムpropTypeを試してください。

 const  childrenPropTypeLogic = (props, propName, componentName) => {
          const prop = props[propName];
          return React.Children
                   .toArray(prop)
                   .find(child => child.type !== 'div') && new Error(`${componentName} only accepts "div" elements`);
 };


static propTypes = {

   children : childrenPropTypeLogic

}

Fiddle

const {Component, PropTypes} = React;

 const  childrenPropTypeLogic = (props, propName, componentName) => {
             var error;
          var prop = props[propName];
    
          React.Children.forEach(prop, function (child) {
            if (child.type !== 'div') {
              error = new Error(
                '`' + componentName + '` only accepts children of type `div`.'
              );
            }
          });
    
          return error;
    };
    
  

class ContainerComponent extends Component {
  static propTypes = {
    children: childrenPropTypeLogic,
  }

  render() {
    return (
      <div>
        {this.props.children}
      </div>
    );
  }
}



class App extends Component {
   render(){
    return (
    <ContainerComponent>
        <div>1</div>
        <div>2</div>
      </ContainerComponent>
    )
   }
}

ReactDOM.render(<App /> , document.querySelector('section'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<section />
1
Abdennour TOUMI