ReactJs: ¿Cuáles deberían ser los PropTypes para this.props.children?

265

Dado un componente simple que representa a sus hijos:

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

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

export default ContainerComponent;

Pregunta: ¿Cuál debería ser el propType del prop de los niños?

Cuando lo configuro como un objeto, falla cuando uso el componente con varios hijos:

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

Advertencia: No se pudo tipo prop: prop no válido childrende tipo array suministrado para ContainerComponent, que se espera object.

Si lo configuro como una matriz, fallará si le doy solo un hijo, es decir:

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

Advertencia: Tipo de utilería fallido: hijos de utilería no válidos del tipo de objeto suministrado a ContainerComponent, matriz esperada.

Por favor avise, ¿no debería molestarme en hacer una verificación de propTypes para elementos secundarios?

d3ming
fuente
Probablemente quierasnode
lux
2
Consulte mi respuesta a continuación que describe más opciones, pero, si está buscando un componente hijo, entonces es PropTypes.element. PropTypes.node describe todo lo que se puede representar: cadenas, números, elementos o una matriz de estas cosas. Si esto te conviene, este es el camino.
ggilberth

Respuestas:

370

Pruebe algo como esto utilizando 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,
}
Alexander Staroselsky
fuente
1
Por desgracia, se produce el mismo error en el caso de uno de los niños: "Advertencia: No se pudo tipo puntal: prop no válida childrendel tipo object... esperaba una matriz."
d3ming
25
¡Eso funciono! La solución más simple es children: PropTypes.nodeque funcionó para ambos casos. Gracias por las sugerencias =)
d3ming
66
Lo único que aclararía esta respuesta sería si incluyera una nota similar a la respuesta de @ggilberth para explicar que React.PropTypes.nodedescribe cualquier objeto renderizable.
theotherjim
No hay necesidad de matriz, solo PropTypes.node. Eso maneja la siguiente corrección: nada, cadena, elemento único, varios elementos, fragmento, componente.
Dima Tisnek
38

Para mí depende del componente. Si sabe con qué necesita que se rellene, debe intentar especificar exclusivamente o varios tipos utilizando:

PropTypes.oneOfType 

Sin embargo, la mayoría de las veces, con componentes más genéricos que pueden tener muchos tipos de hijos, estoy feliz de usar:

PropTypes.any

Si desea hacer referencia a un componente Reaccionar, entonces estará buscando

PropTypes.element

A pesar de que,

PropTypes.node

describe todo lo que se puede representar: cadenas, números, elementos o una serie de estas cosas. Si esto te conviene, este es el camino.

ggilberth
fuente
77
Proptypes.anyEs un tipo muy común. Eslint no está contento con eso.
Alex Shwarc
20

La documentación de PropTypes tiene lo siguiente

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

Por lo tanto, puede usar PropTypes.nodepara buscar objetos o matrices de objetos

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

Las respuestas aquí no parecen abarcar la verificación exacta de los niños. nodey objectson demasiado permisivos, quería verificar el elemento exacto. Esto es lo que terminé usando:

  • Se usa oneOfType([])para permitir niños solos o en conjunto
  • Uso shapey arrayOf(shape({}))para soltero y conjunto de niños, respectivamente
  • Usar oneOfpara el elemento hijo en sí

Al final, algo como esto:

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

Este problema me ayudó a resolver esto más claramente: https://github.com/facebook/react/issues/2979

d3vkit
fuente
5

Si desea hacer coincidir exactamente un tipo de componente, marque esto

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

Si desea hacer coincidir exactamente algunos tipos de componentes, marque esto

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

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

Pruebe un propTypes personalizado:

 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

}

Violín

Abdennour TOUMI
fuente
0

Ejemplo:

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;

Imagen: muestra un error en la consola si el tipo esperado es diferente

Imagen: muestra un error en la consola si el tipo esperado es diferente

Алексей Бируля
fuente