Você quer solicitar um recurso ou relatar um bug ?
Apenas perguntas
Na documentação oficial do React do React.Children você pode ler que this.props.children
é uma "estrutura de dados opaca".
O que isso significa EXATAMENTE?
Acho que existem, em geral, três possibilidades para a transparência da estrutura de dados de props.children
:
props.children
são abertos e bem definidos.Se isso estivesse certo, o termo "estrutura de dados opaca" estaria completamente errado.
Portanto, o "Caso 1" obviamente não é o caso.
props.children
está aberto ou limpo.Isso significa que sempre que você usar props.children
você SEMPRE PRECISA usá-lo em combinação com React.Children
pois React.Children
é o único (mmmh, é realmente o único?) quem sabe sobre a estrutura de dados real de props.children
.
Mas isso implicaria que não deveria ser permitido usar
javascript
// This is used almost everywhere (even in the official React documentation)
<div>{this.props.children}</div>
nem
javascript
// This is often seen with the "Function as child" pattern
MyComponent.propTypes = {
children: PropTypes.func.isRequired,
};
Como os dois exemplos são muito comuns, parece que o "Caso 2" obviamente também não é o caso.
props.children
estão abertos e bem definidos.Isso abriria a possibilidade de que um ou mesmo ambos os exemplos no "Caso 2" sejam válidos.
Mas então isso significaria que deveria haver uma especificação exata de quais aspectos de props.children
estão bem e abertamente definidos e quais aspectos são realmente opacos.
Talvez eu tenha esquecido algo na documentação do React, mas acho que não está exatamente especificado lá, está?
Por que exatamente props.children
não é no caso de haver alguns filhos (um ou mais) apenas sempre um array (como é feito em "Preact" por exemplo)? Isso tornaria as coisas muito mais fáceis, não é?
Muito obrigado desde já pelos esclarecimentos.
_Estrutura de dados opaca_ refere-se ao fato de que children
pode ser muitas coisas: matrizes, fragmentos, elementos únicos, literais de string, etc.
_React.Children_ contém alguns métodos que permitem que você trabalhe com os diferentes tipos de children
_de uma forma unificada_, e definitivamente não é a única maneira de interagir com eles.
Por que exatamente props.children no caso de haver alguns filhos (um ou mais) apenas sempre um array (como é feito em "Preact" por exemplo)?
Além do fato de ter uma abreviação em JSX, children
é uma propriedade como qualquer outra. Na verdade, você pode especificá-lo como:
<Component children={...}/>
Quando o React precisa atualizar o DOM, seria muito mais caro dizer se duas matrizes de item único são iguais do que se dois valores primitivos (por exemplo, strings) são iguais.
Dito isso, acho que a documentação do React.Children pode ser um pouco expandida, mas isso é um problema para registrar no repositório reactjs / reactjs.org .
Este artigo pode esclarecer um pouco as coisas, ele fez por mim!
Muito obrigado @danburzo por suas respostas e esclarecimentos.
Depois de sua resposta, está claro que não entendi completamente a palavra "opaco" aqui.
A documentação do React queria apenas dizer que a estrutura de dados de props.children
é um tipo de união completamente bem definido e que varia em sua representação concreta (como os tipos de união sempre fazem).
Acabei de encontrar um problema antigo que abordava exatamente o mesmo tópico - me pergunto o que aconteceu com essas mudanças?!? (Eu abri um problema em reactjs.org => reactjs / reactjs.org # 914):
https://github.com/facebook/react/pull/6018/files/91223423410f107ff83a8a6ce3158c488247292f?short_path=ef51787#diff -ef51787305cfed62f6f564284762d4de
No entanto, ainda gostaria de fazer a segunda pergunta novamente:
Por que "props.children" NÃO é um array no caso de haver exatamente UM filho (realmente parece uma violação do princípio de menor espanto se você não conhece o fundo => se o nome é "filhos" ou "itens" ou "tokens" que você normalmente espera uma coleção)?
É realmente por motivos de desempenho? Eu realmente não consigo ver que o cálculo de "checkResult" abaixo é tão demorado:
const
child1 = ...,
child2 = ...,
child1IsArray = Array.isArray(child1),
child2IsArray = Array.isArray(child2),
checkResult = child1IsArray && child2IsArray
&& child1.length === 1 && child2.length === 1
&& child1[0] === child2[0];
Desculpe se perguntar novamente parece um pouco chato - mas eu realmente adoraria saber o motivo exato para essa decisão de design ...
Estou feliz por ter ajudado com a primeira parte de sua pergunta! Infelizmente, quanto ao motivo pelo qual filhos únicos não são representados como uma matriz de item único, não tenho uma resposta _exata_. No entanto, eu estava tentando apontar que você ainda pode validamente passar uma única criança como um suporte normal (em vez da abreviação JSX), um fato que eu acidentalmente obscurei com minha hipótese de que está relacionado ao desempenho.
@danburzo Obrigado novamente por sua resposta.
Mmh, francamente, eu esperava que talvez alguém da equipe React se lembrasse do motivo real para essa decisão de design ...
Porque existem realmente alguns problemas sutis com o manuseio de objetos infantis no React.
Por exemplo, pergunte a um novato do React se os componentes Test1 e Test2 no exemplo a seguir se comportam da mesma forma (você - como um profissional do React - sabe que a resposta é "não" => Test2 avisará no DEV sobre as chaves ausentes enquanto Test1 irá não - mas isso é realmente o que você esperaria se fosse um novato?!?)
const
h = React.createElement,
Test1 = () => h('div', null, h('br'), h('br')),
Test2 = () => h('div', { children: [h('br'), h('br')] });
ReactDOM.render(
h('div', null, h(Test1), h(Test2)),
document.getElementById('container')
);
A propósito: Se Test2 fosse permitido, isso teria alguns benefícios de desempenho sutis se você estiver implementando algumas substituições de createElement
- como alguma função de hiperescrito, por exemplo.
Outro exemplo: pergunte a um novato do React como seria "children: PropTypes ...." se o requisito fosse que todos os filhos satisfaçam uma determinada condição. Acho que não seria fácil responder (pelo menos para um novato).
Para a equipe React: Se as razões para a decisão de design em questão não forem realmente conhecidas ou talvez apenas uma questão de gosto, então, é claro, fique à vontade para encerrar este problema.
Presumo que a decisão de não usar uma matriz para um único filho foi tomada para evitar alocações de matriz desnecessárias.
Porque existem realmente alguns problemas sutis com o manuseio de objetos infantis no React.
Geralmente não recomendamos o uso de um children
prop explícito. A maioria dos usuários também usa JSX em vez de chamar diretamente React.createElement
, portanto, os problemas que você mencionou normalmente não são um problema.
@aweary Obrigado pela sua resposta
Comentários muito úteis
_Estrutura de dados opaca_ refere-se ao fato de que
children
pode ser muitas coisas: matrizes, fragmentos, elementos únicos, literais de string, etc._React.Children_ contém alguns métodos que permitem que você trabalhe com os diferentes tipos de
children
_de uma forma unificada_, e definitivamente não é a única maneira de interagir com eles.Além do fato de ter uma abreviação em JSX,
children
é uma propriedade como qualquer outra. Na verdade, você pode especificá-lo como:Quando o React precisa atualizar o DOM, seria muito mais caro dizer se duas matrizes de item único são iguais do que se dois valores primitivos (por exemplo, strings) são iguais.
Dito isso, acho que a documentação do React.Children pode ser um pouco expandida, mas isso é um problema para registrar no repositório reactjs / reactjs.org .
Este artigo pode esclarecer um pouco as coisas, ele fez por mim!