Estou tentando encontrar a maneira correta de definir alguns componentes que podem ser usados de maneira genérica:
<Parent>
<Child value="1">
<Child value="2">
</Parent>
Existe uma lógica em andamento para renderização entre componentes pai e filho, é claro, você pode imaginar <select>
e <option>
como um exemplo dessa lógica.
Esta é uma implementação fictícia para o objetivo da pergunta:
var Parent = React.createClass({
doSomething: function(value) {
},
render: function() {
return (<div>{this.props.children}</div>);
}
});
var Child = React.createClass({
onClick: function() {
this.props.doSomething(this.props.value); // doSomething is undefined
},
render: function() {
return (<div onClick={this.onClick}></div>);
}
});
A pergunta é sempre que você usa {this.props.children}
para definir um componente de wrapper, como você transmite alguma propriedade para todos os seus filhos?
javascript
reactjs
react-jsx
mais-
fonte
fonte
Respostas:
Clonando crianças com novos adereços
Você pode usar React.Children para iterar sobre os filhos e, em seguida, clonar cada elemento com novos adereços (mesclado superficialmente) usando React.cloneElement, por exemplo:
Fiddle: https://jsfiddle.net/2q294y43/2/
Chamando crianças como uma função
Você também pode passar adereços para crianças com adereços de renderização . Nesta abordagem, os filhos (que podem ser
children
ou qualquer outro nome de prop) são uma função que pode aceitar todos os argumentos que você deseja passar e retorna os filhos:Em vez de
<React.Fragment>
ou simplesmente,<>
você também pode retornar uma matriz, se preferir.Fiddle: https://jsfiddle.net/ferahl/y5pcua68/7/
fonte
value
passado paradoSomething
é perdido.Para uma maneira um pouco mais limpa, tente:
Editar: Para usar com vários filhos individuais (o filho deve ser um componente), você pode fazer. Testado em 16.8.6
fonte
this.props.children
) paracloneElement
... que está esperando um ... elemento.React.Children.only
A função retorna o único filho ou lança uma exceção se houver vários (isso não existiria se não houvesse um caso de uso).Tente isto
Funcionou para mim usando o react-15.1.
fonte
React.cloneElement()
diretamente sem colocá-lo em<div>
tags? Porque e se a criança for<span>
(ou outra coisa) e quisermos preservar seu tipo de elemento de tag?React.cloneElement(React.Children.only(this.props.children), {...this.props})
um erro que passará mais de um filho. Então você não precisa agrupar uma div.let {children, ...acyclicalProps} = this.props
e entãoReact.cloneElement(React.Children.only(children), acyclicalProps)
.Passe adereços para direcionar as crianças.
Veja todas as outras respostas
Passe dados globais compartilhados pela árvore de componentes via contexto
Isenção de responsabilidade: esta é uma resposta atualizada, a anterior usou a API de contexto antiga
É baseado no princípio Consumidor / Fornecer. Primeiro, crie seu contexto
Em seguida, use via
e
Exemplo completo, semi-pseudo-código.
1 https://facebook.github.io/react/docs/context.html
fonte
this.context
) - não magicamente mesclava o contexto com adereços. Você tinha que intencionalmente definir e usar o contexto, o que é uma coisa totalmente diferente.Passando adereços para crianças aninhadas
Com a atualização para o React 16.6, agora você pode usar React.createContext e contextType .
fonte
this
contextoVocê pode usar
React.cloneElement
, é melhor saber como funciona antes de começar a usá-lo em seu aplicativo. É introduzidoReact v0.13
, continue a ler para obter mais informações; portanto, algo junto com este trabalho para você:Portanto, traga as linhas da documentação do React para que você entenda como tudo está funcionando e como você pode usá-las:
mais aqui ...
fonte
A melhor maneira, que permite fazer a transferência de propriedade, é
children
como uma funçãoExemplo:
fonte
nested components
. React não possui padrões aninhados, apenas composições. Sim, os filhos devem ser uma função, não há conflitos, porque esse é o filho JSX válido. Você pode dar um exemplo comnesting components
?<Parent>{props => <Nest><ChildComponent /></Nest>}</Parent>
, em vez de (não funciona)<Parent><Nest>{props => <ChildComponent />}</Nest></Parent>
, então eu concordo que isso é a melhor respostaTypeError: children is not a function
Eu precisava corrigir a resposta aceita acima para fazê-la funcionar usando isso em vez deste ponteiro. Isso no escopo da função map não tinha a função doSomething definida.
Atualização: essa correção é para o ECMAScript 5, no ES6 não é necessário var que = isto
fonte
bind()
doSomething
tomou um objeto, comodoSomething: function(obj) { console.log(obj) }
e no Menino você chamariathis.props.doSomething(obj)
para fazer logout"obj"
apply
método O usobind()
da função de renderização criará uma nova função sempre que o método de renderização for chamado.Maneira mais limpa considerando um ou mais filhos
fonte
this.props
. Em geral, eu recomendaria apenas a clonagem com adereços específicos, e não o shebang inteiro.{...this.props}
não funcionou para mim, é o caminho{...child.props}
correto?React.Children.map(children, child => React.cloneElement(child, props))
Nenhuma das respostas aborda a questão de ter filhos que não são componentes do React, como seqüências de caracteres de texto. Uma solução alternativa pode ser algo como isto:
fonte
Você não precisa mais
{this.props.children}
. Agora você pode agrupar o componente filho usandorender
inRoute
e passar seus adereços como de costume:fonte
Parent.jsx:
Child.jsx:
e main.jsx:
veja o exemplo aqui: https://plnkr.co/edit/jJHQECrKRrtKlKYRpIWl?p=preview
fonte
Talvez você também considere útil esse recurso, embora muitas pessoas o considerem um antipadrão, ele ainda pode ser usado se você souber o que está fazendo e projetar bem sua solução.
Função como componentes filhos
fonte
Se você tem vários filhos aos quais deseja passar adereços , pode fazê-lo desta maneira, usando o mapa React.Children.map:
Se o seu componente está tendo apenas um filho, não há necessidade de mapeamento, basta clonar o elemento imediatamente:
fonte
De acordo com a documentação do
cloneElement()
Portanto, cloneElement é o que você usaria para fornecer adereços personalizados para os filhos. No entanto, pode haver vários filhos no componente e você precisará fazer um loop sobre ele. O que outras respostas sugerem é que você as mapeie usando
React.Children.map
. No entanto,React.Children.map
ao contrário dasReact.cloneElement
alterações, as teclas do elemento anexado e extra.$
como prefixo. Verifique esta pergunta para obter mais detalhes: React.cloneElement dentro de React.Children.map está causando alterações nas chaves dos elementosSe você deseja evitá-lo, deve executar a
forEach
função comofonte
Além da resposta @and_rest, é assim que clono as crianças e adiciono uma classe.
fonte
Eu acho que um suporte de renderização é a maneira apropriada de lidar com esse cenário
Você permite que o pai forneça os adereços necessários usados no componente filho, refatorando o código pai para se parecer com algo assim:
Em seguida, no componente filho, você pode acessar a função fornecida pelo pai desta maneira:
Agora a estrutura do noivo ficará assim:
fonte
Método 1 - clonar crianças
Método 2 - usar contexto compositável
O contexto permite que você transmita um suporte a um componente filho profundo sem transmiti-lo explicitamente como um suporte pelos componentes intermediários.
O contexto vem com desvantagens:
Usando um contexto compositável
fonte
{children}:{children:ReactNode}
?"children"
é do tipoReactNode
A maneira mais eficiente de fazer isso:
fonte
Para qualquer pessoa que tenha um único elemento filho, isso deve ser feito.
fonte
É isso que você precisa?
fonte
Por alguma razão, o React.children não estava trabalhando para mim. Isto é o que funcionou para mim.
Eu queria apenas adicionar uma classe à criança. semelhante a alterar um suporte
O truque aqui é o React.cloneElement . Você pode aprovar qualquer suporte de maneira semelhante
fonte
Render adereços é a abordagem mais precisa para esse problema. Em vez de passar o componente filho para o componente pai como adereços filhos, deixe o pai renderizar o componente filho manualmente. Render é adereços embutidos no react, que recebe o parâmetro de função. Nesta função, você pode deixar o componente pai renderizar o que quiser com parâmetros personalizados. Basicamente, faz o mesmo que adereços filhos, mas é mais personalizável.
Exemplo no codepen
fonte
Ao usar componentes funcionais, você geralmente recebe o
TypeError: Cannot add property myNewProp, object is not extensible
erro ao tentar definir novas propriedadesprops.children
. Existe uma solução para isso clonando os adereços e depois a criança com os novos adereços.fonte