Étant donné un composant simple qui rend ses enfants:
class ContainerComponent extends Component {
static propTypes = {
children: PropTypes.object.isRequired,
}
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
export default ContainerComponent;
Question: Quel doit être le type de propriété de la propriété enfants?
Lorsque je le configure en tant qu'objet, il échoue lorsque j'utilise le composant avec plusieurs enfants:
<ContainerComponent>
<div>1</div>
<div>2</div>
</ContainerComponent>
Avertissement: Type de prop échoué: Prop incorrect
children
de typearray
fourni àContainerComponent
, attenduobject
.
Si je le configure en tant que tableau, il échouera si je ne lui donne qu'un enfant, c'est-à-dire:
<ContainerComponent>
<div>1</div>
</ContainerComponent>
Avertissement: Type de prop ayant échoué: enfants de prop non valides de type objet fournis à ContainerComponent, tableau attendu.
S'il vous plaît aviser, ne devrais-je pas juste me donner la peine de faire une vérification propTypes pour les éléments enfants?
Essayez quelque chose comme ceci en utilisant oneOfType
ou PropTypes.node
import PropTypes from 'prop-types'
...
static propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]).isRequired
}
ou
static propTypes = {
children: PropTypes.node.isRequired,
}
Pour moi, cela dépend du composant. Si vous savez ce dont vous avez besoin pour cela, vous devriez essayer de spécifier exclusivement, ou plusieurs types en utilisant:
PropTypes.oneOfType
Cependant, je trouve surtout, avec des composants plus génériques pouvant avoir plusieurs types d’enfants, que j’aimerais utiliser:
PropTypes.any
Si vous souhaitez faire référence à un composant React, vous rechercherez
PropTypes.element
Bien que,
PropTypes.node
décrit tout ce qui peut être rendu - des chaînes, des nombres, des éléments ou un tableau de ces choses. Si cela vous convient, c'est ainsi.
La documentation PropTypes a le suivant
// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
optionalNode: PropTypes.node,
Donc, vous pouvez utiliser PropTypes.node
pour rechercher des objets ou des tableaux d'objets
static propTypes = {
children: PropTypes.node.isRequired,
}
Les réponses ici ne semblent pas couvrir tout à fait la vérification des enfants exactement. node
et object
sont trop permissifs, je voulais vérifier l'élément exact. Voici ce que j'ai fini par utiliser:
oneOfType([])
pour autoriser un ou plusieurs enfantsshape
et arrayOf(shape({}))
pour un enfant et un tableau d'enfants, respectivementoneOf
pour l'élément enfant lui-mêmeEn fin de compte, quelque chose comme ça:
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
Ce problème m'a aidé à comprendre cela plus clairement: https://github.com/facebook/react/issues/2979
Si vous voulez faire correspondre exactement un type de composant, cochez cette case.
MenuPrimary.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(MenuPrimaryItem),
PropTypes.objectOf(MenuPrimaryItem)
])
}
Si vous voulez faire correspondre exactement certains types de composants, cochez cette case.
const HeaderTypes = [
PropTypes.objectOf(MenuPrimary),
PropTypes.objectOf(UserInfo)
]
Header.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.oneOfType([...HeaderTypes])),
...HeaderTypes
])
}
Essayez un type de propriété personnalisé:
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 />