ReactJs: quali dovrebbero essere i PropTypes per this.props.children?


265

Dato un componente semplice che rende i suoi figli:

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

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

export default ContainerComponent;

Domanda: quale dovrebbe essere il propType del puntello per bambini?

Quando lo imposto come oggetto, non riesce quando utilizzo il componente con più figli:

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

Avviso: impossibile Tipo prop: prop non valido childrendi tipo array in dotazione per ContainerComponent, atteso object.

Se lo imposto come un array, fallirà se gli darò solo un figlio, ovvero:

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

Avvertenza: tipo di prop non riuscito: elementi secondari di prop non validi di tipo oggetto forniti a ContainerComponent, array previsto.

Si prega di avvisare, non dovrei preoccuparmi di fare un controllo propTypes per gli elementi dei bambini?


Probabilmente vuoinode
lux


2
Si prega di vedere la mia risposta sotto che descrive più opzioni, ma, se stai cercando un componente figlio, allora è PropTypes.element. PropTypes.node descrive tutto ciò che può essere reso - stringhe, numeri, elementi o un array di queste cose. Se ti va bene, allora è così.
ggilberth,

Risposte:


370

Prova qualcosa di simile utilizzando oneOfTypeoPropTypes.node

import PropTypes from 'prop-types'

...

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

o

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

1
Purtroppo non riesce con lo stesso errore nel caso singolo bambino: "Attenzione: Impossibile Tipo prop: prop non valido childrendi tipo object. ... aspetta una matrice"
3

25
Ha funzionato! La soluzione più semplice è children: PropTypes.nodequella che ha funzionato in entrambi i casi. Grazie per i suggerimenti =)
d3ming

6
L'unica cosa che renderebbe più chiara questa risposta sarebbe se tu includessi una nota simile alla risposta di @ggilberth per spiegare che React.PropTypes.nodedescrive qualsiasi oggetto renderizzabile.
theotherjim,

Non c'è bisogno di array, solo PropTypes.node. Che gestisce la seguente correzione: niente, stringa, singolo elemento, diversi elementi, frammento, componente.
Dima Tisnek,

38

Per me dipende dal componente. Se sai di cosa hai bisogno per essere popolato allora dovresti provare a specificare esclusivamente, o più tipi usando:

PropTypes.oneOfType 

Comunque trovo principalmente, con componenti più generici che possono avere molti tipi di figli, sono felice di usare:

PropTypes.any

Se vuoi fare riferimento a un componente React, allora cercherai

PropTypes.element

Sebbene,

PropTypes.node

descrive tutto ciò che può essere reso - stringhe, numeri, elementi o una matrice di queste cose. Se ti va bene, allora è così.


7
Proptypes.anyè un tipo troppo comune. Eslint non ne è contento.
Alex Shwarc,

20

La documentazione PropTypes contiene quanto segue

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

Quindi, è possibile utilizzare PropTypes.nodeper verificare la presenza di oggetti o matrici di oggetti

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

12

Le risposte qui non sembrano riguardare esattamente il controllo dei bambini. nodee objectsono troppo permissivo, volevo controllare l'elemento esatto. Ecco cosa ho finito per usare:

  • Utilizzare oneOfType([])per consentire single o array di bambini
  • Utilizzare shapee arrayOf(shape({}))per single e array di bambini, rispettivamente
  • Utilizzare oneOfper l'elemento figlio stesso

Alla fine, qualcosa del genere:

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

Questo problema mi ha aiutato a capirlo più chiaramente: https://github.com/facebook/react/issues/2979


5

Se si desidera abbinare esattamente un tipo di componente, controllare questo

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

Se si desidera abbinare esattamente alcuni tipi di componenti, controllare questo

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

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

2

Prova un propTypes personalizzato:

 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

}

Violino


0

Esempio:

import React from 'react';
import PropTypes from 'prop-types';

class MenuItem extends React.Component {
    render() {
        return (
            <li>
                <a href={this.props.href}>{this.props.children}</a>
            </li>
        );
    }
}

MenuItem.defaultProps = {
    href: "/",
    children: "Main page"
};

MenuItem.propTypes = {
    href: PropTypes.string.isRequired,
    children: PropTypes.string.isRequired
};

export default MenuItem;

Immagine: mostra un errore nella console se il tipo previsto è diverso

Immagine: mostra un errore nella console se il tipo previsto è diverso

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.