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?


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

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.


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

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


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
  ])
}

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


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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.