ReactJs: Quais devem ser os PropTypes para this.props.children?

265

Dado um componente simples que gera seus filhos:

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

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

export default ContainerComponent;

Pergunta: Qual deve ser o propType das crianças prop?

Quando eu o defino como objeto, ele falha quando uso o componente com vários filhos:

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

Aviso: Tipo de suporte com falha: suporte inválido childrendo tipo array fornecido para ContainerComponent, esperado object.

Se eu defini-lo como uma matriz, ele falhará se eu der apenas um filho, ou seja:

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

Aviso: Tipo de suporte com falha: filhos de objetos inválidos do objeto de tipo fornecidos ao ContainerComponent, matriz esperada.

Por favor, informe, eu não deveria me incomodar em fazer uma verificação de propTypes para elementos child?

d3ming
fonte
Você provavelmente quernode
lux
2
Por favor, veja minha resposta abaixo que descreve mais opções, mas, se você estiver procurando por um componente filho, então é PropTypes.element. PropTypes.node descreve qualquer coisa que possa ser renderizada - strings, números, elementos ou uma matriz dessas coisas. Se isso combina com você, então este é o caminho.
precisa saber é o seguinte

Respostas:

369

Tente algo assim utilizando oneOfTypeouPropTypes.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,
}
Alexander Staroselsky
fonte
1
Infelizmente ele falha com o mesmo erro no caso de um único filho: "Aviso: Falha tipo prop: prop inválido childrendo tipo object... espera um array."
d3ming 8/17
25
Isso funcionou! A solução mais simples é children: PropTypes.nodeque funcionou para os dois casos. Obrigado pelas sugestões =)
d3ming 08/02
6
A única coisa que tornaria essa resposta mais clara seria se você incluísse uma observação semelhante à resposta de @ggilberth para explicar que React.PropTypes.nodedescreve qualquer objeto renderizável.
theotherjim
Não há necessidade de matriz, apenas PropTypes.node. Isso lida com a seguinte correção: nada, sequência, elemento único, vários elementos, fragmento, componente.
Dima Tisnek 27/09/19
38

Para mim, depende do componente. Se você sabe com o que precisa ser preenchido, tente especificar exclusivamente ou vários tipos usando:

PropTypes.oneOfType 

No entanto, na maioria das vezes, acho que, com componentes mais genéricos que podem ter muitos tipos de filhos, fico feliz em usar:

PropTypes.any

Se você quiser se referir a um componente React, estará procurando

PropTypes.element

Apesar,

PropTypes.node

descreve qualquer coisa que possa ser renderizada - strings, números, elementos ou uma matriz dessas coisas. Se isso combina com você, então este é o caminho.

ggilberth
fonte
7
Proptypes.anyé um tipo muito comum. Eslint não está feliz com isso.
precisa saber é o seguinte
20

A documentação do PropTypes possui os seguintes

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

Então, você pode usar PropTypes.nodepara verificar se há objetos ou matrizes de objetos

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

As respostas aqui não parecem abranger a verificação exata das crianças. nodee objectsão muito permissivos, eu queria verificar o elemento exato. Aqui está o que eu acabei usando:

  • Use oneOfType([])para permitir um único ou vários filhos
  • Use shapee arrayOf(shape({}))para um e vários filhos, respectivamente
  • Use oneOfpara o próprio elemento filho

No final, algo parecido com isto:

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

Esse problema me ajudou a descobrir isso com mais clareza: https://github.com/facebook/react/issues/2979

d3vkit
fonte
5

Se você deseja corresponder exatamente a um tipo de componente, verifique este

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

Se você deseja corresponder exatamente a alguns tipos de componentes, verifique este

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

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

Experimente um suporte 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

}

Violino

Abdennour TOUMI
fonte
0

Exemplo:

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;

Imagem: mostra um erro no console se o tipo esperado for diferente

Imagem: mostra um erro no console se o tipo esperado for diferente

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