Não existe uma maneira simples de transmitir uma criança props
ao pai usando eventos, no React.js?
var Child = React.createClass({
render: function() {
<a onClick={this.props.onClick}>Click me</a>
}
});
var Parent = React.createClass({
onClick: function(event) {
// event.component.props ?why is this not available?
},
render: function() {
<Child onClick={this.onClick} />
}
});
Eu sei que você pode usar componentes controlados para passar o valor de uma entrada, mas seria bom passar o kit todo no kaboodle. Às vezes, o componente filho contém um conjunto de informações que você prefere não procurar.
Talvez haja uma maneira de vincular o componente ao evento?
ATUALIZAÇÃO - 1/9/2015
Depois de usar o React por mais de um ano, e estimulado pela resposta de Sebastien Lorber, concluí que a transmissão de componentes filhos como argumentos para funções nos pais não é , de fato, o modo React, nem nunca foi uma boa idéia. Eu mudei a resposta.
javascript
reactjs
KendallB
fonte
fonte
Respostas:
Editar : veja os exemplos finais para ver os exemplos atualizados do ES6.
Essa resposta simplesmente trata do caso de relacionamento direto pai-filho. Quando pai e filho têm potencialmente muitos intermediários, verifique esta resposta .
Outras soluções estão faltando
Enquanto eles ainda funcionam bem, outras respostas estão faltando algo muito importante.
Os pais já têm esse suporte filho! : se a criança tem um suporte, é porque seus pais forneceram esse suporte à criança! Por que você quer que a criança devolva o suporte aos pais, enquanto os pais obviamente já têm esse suporte?
Melhor implementação
Criança : realmente não precisa ser mais complicado que isso.
Pai com filho único : usando o valor que ele passa para o filho
JsFiddle
Pai com lista de filhos : você ainda tem tudo o que precisa no pai e não precisa tornar a criança mais complicada.
JsFiddle
Também é possível usar
this.handleChildClick.bind(null,childIndex)
e depois usarthis.state.childrenData[childIndex]
Observe que estamos vinculando um
null
contexto porque, caso contrário, o React emite um aviso relacionado ao seu sistema de vinculação automática. Usar nulo significa que você não deseja alterar o contexto da função. Veja também .Sobre encapsulamento e acoplamento em outras respostas
Isso é para mim uma péssima idéia em termos de acoplamento e encapsulamento:
Usando adereços : Como expliquei acima, você já possui os adereços no pai, portanto é inútil passar todo o componente filho para acessar os adereços.
Usando refs : você já tem o destino do clique no evento e, na maioria dos casos, isso é suficiente. Além disso, você poderia ter usado um árbitro diretamente na criança:
E acesse o nó DOM no pai com
Para casos mais avançados em que você deseja acessar várias referências do filho no pai, o filho pode passar todos os nós de domínio diretamente no retorno de chamada.
O componente tem uma interface (props) e o pai não deve assumir nada sobre o trabalho interno do filho, incluindo sua estrutura DOM interna ou para quais nós DOM ele declara refs. Um pai que usa uma referência de um filho significa que você acopla firmemente os 2 componentes.
Para ilustrar o problema, levarei esta citação sobre o Shadow DOM , que é usado dentro dos navegadores para renderizar coisas como controles deslizantes, barras de rolagem, players de vídeo ...:
O problema é que, se você deixar os detalhes da implementação filho vazarem para o pai, dificulta a refatoração do filho sem afetar o pai. Isso significa que, como autor da biblioteca (ou como editor do navegador com o Shadow DOM), isso é muito perigoso, porque você deixa o cliente acessar demais, dificultando a atualização do código sem interromper a retrocompatibilidade.
Se o Chrome implementou sua barra de rolagem, permitindo que o cliente acesse os nós de domínio internos dessa barra de rolagem, isso significa que o cliente pode ter a possibilidade de simplesmente quebrar essa barra de rolagem e que os aplicativos quebrariam mais facilmente quando o Chrome executasse sua atualização automática após refatorar o barra de rolagem ... Em vez disso, eles apenas dão acesso a algumas coisas seguras, como personalizar algumas partes da barra de rolagem com CSS.
Sobre como usar qualquer outra coisa
Passando toda a componente no callback é perigoso e pode levar desenvolvedores novatos para fazer coisas muito estranhas como a chamada
childComponent.setState(...)
ouchildComponent.forceUpdate()
, ou atribuindo-lhe novas variáveis, dentro do pai, fazendo com que o aplicativo inteiro muito mais difícil de raciocinar sobre.Edit: ES6 examples
Como muitas pessoas agora usam o ES6, eis os mesmos exemplos de sintaxe do ES6
A criança pode ser muito simples:
O pai pode ser uma classe (e, eventualmente, pode gerenciar o próprio estado, mas estou passando isso como adereços aqui:
Mas também pode ser simplificado se não for necessário gerenciar o estado:
JsFiddle
AVISO PERF (aplicável ao ES5 / ES6): se você estiver usando
PureComponent
oushouldComponentUpdate
, as implementações acima não serão otimizadas por padrão porque usamonClick={e => doSomething()}
ou vinculam diretamente durante a fase de renderização, porque criarão uma nova função sempre que o pai for renderizado. Se esse é um gargalo perfeito no seu aplicativo, você pode passar os dados para os filhos e reiniciá-los no retorno de chamada "estável" (definido na classe pai e vinculado aothis
construtor da classe) para que aPureComponent
otimização possa ser ativada ou você pode implementar o seu próprioshouldComponentUpdate
e ignorar o retorno de chamada na verificação de comparação de adereços.Você também pode usar a biblioteca Recompose , que fornece componentes de ordem superior para obter otimizações aprimoradas:
Nesse caso, você pode otimizar o componente filho usando:
fonte
props
. Aceita?How do I know which of my children was chosen among a group?
isso realmente não faz parte da pergunta original, mas incluí a solução na minha resposta. Ao contrário da sua edição, acho que não é necessário modificar o filho, mesmo ao lidar com uma lista, pois você pode usá-lobind
diretamente no pai.onClick={this.handleChildClick.bind(null,childData)}
você mencionou sobre a ligação automática Isso ainda é aplicável agora que o React não foi incluído no modelo de classe . Eu li muitas coisas, mas essa parte ainda me confunde. Aclass model
propósito, estou usando o ES6 , então mudeinull
parathis
e meu código ainda parece funcionar. Como você traduziria essa parte do seu código em um estilo ES6?Atualização (1/9/15): O OP transformou essa questão em um alvo em movimento. Foi atualizado novamente. Portanto, sinto-me responsável por atualizar minha resposta.
Primeiro, uma resposta para o seu exemplo fornecido:
Sim, isso é possível.
Você pode resolver isso atualizando Child's
onClick
comothis.props.onClick.bind(null, this)
:O manipulador de eventos em seu pai pode acessar o componente e o evento da seguinte forma:
Instantâneo JSBin
Mas a pergunta em si é enganosa
O pai já conhece o filho
props
.Isso não está claro no exemplo fornecido, porque na verdade não há props. Esse código de exemplo pode suportar melhor a pergunta que está sendo feita:
Torna-se muito mais claro neste exemplo que você já sabe quais são os objetos de criança.
Instantâneo JSBin
Se é realmente sobre o uso de adereços de uma criança ...
Se realmente se trata de usar adereços de uma criança, você pode evitar qualquer conexão com a criança completamente.
O JSX possui uma API de atributos de propagação que costumo usar em componentes como Child. Ele pega todos os
props
e os aplica a um componente. Criança ficaria assim:Permitindo que você use os valores diretamente no Pai:
Instantâneo JSBin
E não é necessária nenhuma configuração adicional à medida que você conecta componentes filho adicionais
Instantâneo JSBin
Mas suspeito que esse não seja seu caso de uso real. Então vamos cavar mais ...
Um exemplo prático robusto
A natureza genérica do exemplo fornecido é difícil de falar. Eu criei um componente que demonstra um uso prático para a pergunta acima, implementado de uma maneira muito reativa :
Exemplo de trabalho do
DTServiceCalculator DTServiceCalculator repo
Este componente é uma calculadora de serviço simples. Você fornece uma lista de serviços (com nomes e preços) e calcula um total dos preços selecionados.
As crianças são alegremente ignorantes
ServiceItem
é o componente filho neste exemplo. Não tem muitas opiniões sobre o mundo exterior. Ele requer alguns adereços , uma das quais é uma função a ser chamada quando clicado.<div onClick={this.props.handleClick.bind(this.props.index)} />
Ele não faz nada além de chamar o
handleClick
retorno de chamada fornecido com aindex
[ origem ] fornecida .Os pais são filhos
DTServicesCalculator
é o componente pai é este exemplo. Também é uma criança. Vamos olhar.DTServiceCalculator
cria uma lista de componentes filhosServiceItem
e fornece a eles adereços [ origem ]. É o componente pai de,ServiceItem
mas é o componente filho do componente que está passando na lista. Não possui os dados. Por isso, novamente delega a manipulação do componente à sua origem do componente pai<ServiceItem chosen={chosen} index={i} key={id} price={price} name={name} onSelect={this.props.handleServiceItem} />
handleServiceItem
captura o índice, transmitido do filho e o fornece ao pai [ origem ]Os proprietários sabem tudo
O conceito de "Propriedade" é importante no React. Eu recomendo ler mais sobre isso aqui .
No exemplo que mostrei, continuo delegando a manipulação de um evento na árvore de componentes até chegarmos ao componente que possui o estado.
Quando finalmente chegamos lá, lidamos com a seleção / desmarcação de estado da seguinte forma [ fonte ]:
Conclusão
Tente manter os componentes mais externos o mais opaco possível. Esforce-se para garantir que eles tenham muito poucas preferências sobre como um componente pai pode optar por implementá-los.
Lembre-se de quem possui os dados que você está manipulando. Na maioria dos casos, você precisará delegar eventos que manipulam a árvore para o componente que possui esse estado.
Além disso: o padrão Flux é uma boa maneira de reduzir esse tipo de conexão necessária nos aplicativos.
fonte
Parent
pode ser uma visão do controlador, enquantoChild
é apenas uma visão idiota (componente). Somente Controller-Views deve ter conhecimento do aplicativo. Nesse caso, você ainda passaria a ação deParent
paraChild
como um suporte. No que diz respeito à própria Ação, o Flux possui um padrão fortemente prescrito para interagir entre as Ações para atualizar as Visualizações. facebook.github.io/flux/docs/…onClick={this.onClick.bind(null, this.state.text)}
não há necessidade de vincular o estado, pois o pai tem isso. então sóonClick={this.onClick}
vai funcionar. ondeonClick = ()=>{const text = this.state.text;..}
no paiParece que há uma resposta simples. Considere isto:
A chave está chamando
bind(null, this)
othis.props.onClick
evento, passado pelo pai. Agora, a função onClick aceita argumentoscomponent
, ANDevent
. Eu acho que é o melhor de todos os mundos.ATUALIZAÇÃO: 1/9/2015
Essa foi uma péssima idéia: deixar os detalhes da implementação filho vazarem para o pai nunca foi um bom caminho. Veja a resposta de Sebastien Lorber.
fonte
this
função (que não é necessária de qualquer maneira) e o segundo é anexado como primeiro argumento quando onClick é chamado.A questão é como passar o argumento do componente filho para o componente pai. Este exemplo é fácil de usar e testado:
Veja JSFIDDLE
fonte
Basicamente, você usa adereços para enviar informações de e para Filhos e Pais.
Adicionando a todas as respostas maravilhosas, deixe-me dar um exemplo simples que explica a passagem de valores do componente filho para o componente pai no React
App.js
Header.js
Main.js
É isso, agora você pode passar valores do seu cliente para o servidor.
Dê uma olhada na função Alterar no Header.js
É assim que você insere valores nos objetos do cliente para o servidor
fonte
Aqui está uma implementação simples do ES6 em três etapas usando a ligação de função no construtor pai. Esta é a primeira maneira que o tutorial oficial de reação recomenda (também há sintaxe de campos de classe pública não abordada aqui). Você pode encontrar todas essas informações aqui https://reactjs.org/docs/handling-events.html
Vinculando as funções dos pais para que as crianças possam chamá-las (e passar dados para os pais!: D)
Função dos pais
Construtor pai
Suporte passado para criança
Chamada de evento filho
fonte
Este é um exemplo sem usar o evento onClick. Simplesmente passo uma função de retorno de chamada para a criança por adereços. Com esse retorno de chamada, a chamada secundária também envia os dados de volta. Eu fui inspirado pelos exemplos nos documentos .
Exemplo pequeno (este é um arquivo tsx, portanto, props e estados devem ser declarados completamente, excluí alguma lógica dos componentes, portanto, é menos código).
* Atualização: Importante é vincular isso ao retorno de chamada, caso contrário, o retorno de chamada tem o escopo do filho e não do pai. Único problema: é o pai "velho" ...
SymptomChoser é o pai:
Sintoma é o filho (nos objetos do filho que eu declarei a função de retorno de chamada, na função selectedSymptom o retorno de chamada é chamado):
fonte