子をレンダリングする単純なコンポーネントがあるとします。
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
型のarray
がContainerComponent
に提供されました。予想されるobject
。
配列として設定した場合、1つの子だけを指定すると失敗します。
<ContainerComponent>
<div>1</div>
</ContainerComponent>
Warning:失敗したprop型:ContainerComponentに渡されたobject型の無効なprop子、期待される配列。
アドバイスしてください、私は子供の要素のためにpropTypesのチェックをするのを邪魔してはいけないのですか?
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,
}
私にとっては、コンポーネントによって異なります。必要なものがわかっている場合は、次のようにして排他的に、または複数の型を指定するようにしてください。
PropTypes.oneOfType
しかし、私はほとんどの場合、多くの種類の子を持つことができるより一般的なコンポーネントを使用して、私は使用して嬉しいです
PropTypes.any
Reactコンポーネントを参照したいのなら、あなたは探しているでしょう。
PropTypes.element
が、
PropTypes.node
文字列、数値、要素、またはこれらのものの配列など、レンダリングできるものすべてを記述します。これがあなたに合っているなら、これは方法です。
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,
}
ここでの答えは正確に子供たちをチェックすることをカバーしていないようです。 node
とobject
は寛容すぎるので、正確な要素をチェックしたいと思いました。これが私が使用したものです:
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
コンポーネントの種類と正確に一致させたい場合は、これをチェックしてください。
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
])
}
カスタム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
}
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 />