Digamos que eu tenha um componente de visualização com renderização condicional:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
MyInput é parecido com isto:
class MyInput extends React.Component {
...
render(){
return (
<div>
<input name={this.props.name}
ref="input"
type="text"
value={this.props.value || null}
onBlur={this.handleBlur.bind(this)}
onChange={this.handleTyping.bind(this)} />
</div>
);
}
}
Vamos dizer que employed
é verdade. Sempre que eu mudo para false e a outra visualização é renderizada, apenas unemployment-duration
é reinicializado. Também unemployment-reason
é preenchido com o valor de job-title
(se um valor foi fornecido antes da alteração da condição).
Se eu alterar a marcação na segunda rotina de renderização para algo assim:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<span>Diff me!</span>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Parece que tudo funciona bem. Parece que o React simplesmente falha em diferenciar 'cargo' e 'motivo de desemprego'.
Por favor me diga o que estou fazendo de errado ...
javascript
reactjs
o01
fonte
fonte
data-reactid
em cada um dos elementosMyInput
(ouinput
, como visto no DOM) antes e depois daemployed
troca?<div>
. Osdata-reactid
atributos parecem ser diferentes no div de agrupamento e no campo de entrada.job-title
a entrada obtém iddata-reactid=".0.1.1.0.1.0.1"
, enquanto aunemployment-reason
entrada obtém iddata-reactid=".0.1.1.0.1.2.1"
unemployment-duration
?reactid
atributos são idênticos emjob-title
eunemployment-reason
, enquanto no segundo exemplo (com o intervalo diff) eles são diferentes.unemployment-duration
oreactid
atributo é sempre único.Respostas:
O que provavelmente está acontecendo é que o React pensa que apenas um
MyInput
(unemployment-duration
) é adicionado entre os renderizadores. Como tal,job-title
nunca é substituído porunemployment-reason
, que também é o motivo pelo qual os valores predefinidos são trocados.Quando o React faz a diferença, ele determina quais componentes são novos e quais são antigos com base em suas
key
propriedades. Se nenhuma chave for fornecida no código, ele irá gerar a sua própria.O motivo pelo qual o último trecho de código fornecido funciona é porque o React precisa essencialmente alterar a hierarquia de todos os elementos sob o pai
div
e acredito que isso acionaria uma nova renderização de todos os filhos (é por isso que funciona). Se você tivesse adicionado ospan
na parte inferior em vez de no topo, a hierarquia dos elementos anteriores não mudaria e esses elementos não seriam renderizados novamente (e o problema persistiria).Aqui está o que diz a documentação oficial do React :
Você deve ser capaz de corrigir isso fornecendo um
key
elemento exclusivo para o paidiv
ou para todos osMyInput
elementos.Por exemplo:
OU
Agora, quando o React fizer a diferença, ele verá que
divs
são diferentes e irá renderizá-lo novamente incluindo todos os seus filhos (primeiro exemplo). No segundo exemplo, o diff será um sucesso emjob-title
eunemployment-reason
uma vez que eles agora têm chaves diferentes.É claro que você pode usar as chaves que desejar, desde que sejam exclusivas.
Atualização de agosto de 2017
Para uma melhor compreensão de como as chaves funcionam no React, recomendo fortemente a leitura da minha resposta em Compreendendo as chaves exclusivas no React.js .
Atualização novembro de 2017
Esta atualização deveria ter sido postada há algum tempo, mas o uso de literais de string
ref
agora está obsoleto. Por exemploref="job-title"
, agora deve serref={(el) => this.jobTitleRef = el}
(por exemplo). Consulte minha resposta ao aviso de suspensão de uso usando this.refs para obter mais informações.fonte
it will determine which components are new and which are old based on their key property.
- isso foi ... a chave ... para o meu entendimentoAltere a chave do componente.
O componente será desmontado e uma nova instância do componente será montada, pois a chave foi alterada.
editar : Documentado sobre você Provavelmente não precisa do estado derivado :
fonte
Use
setState
em sua visão para alterar aemployed
propriedade do estado. Este é um exemplo de mecanismo de renderização React.fonte
Estou trabalhando no Crud para meu aplicativo. É assim que eu fiz Got Reactstrap como minha dependência.
Alguns Ganchos React lá
fonte