web-dev-qa-db-fra.com

ReactJs: Quels devraient être les PropTypes pour this.props.children?

É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 type array fourni à ContainerComponent, attendu object.

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?

188
d3ming

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,
}
270

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.

25
ggilberth

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,
}
9
DC.Azndj

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:

  • Utilisez oneOfType([]) pour autoriser un ou plusieurs enfants
  • Utilisez shape et arrayOf(shape({})) pour un enfant et un tableau d'enfants, respectivement
  • Utilisez oneOf pour l'élément enfant lui-même

En 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

6
d3vkit

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
  ])
}
4
Andrew Luca

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

}

violon

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 />
2
Abdennour TOUMI