Digamos que tengo un componente de vista que tiene un render 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 se parece a esto:
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>
);
}
}
Digamos que employed
es verdad. Siempre que lo cambio a falso y la otra vista se procesa, solo unemployment-duration
se reinicializa. También unemployment-reason
se rellena previamente con el valor de job-title
(si se dio un valor antes de que cambiara la condición).
Si cambio el marcado en la segunda rutina de renderizado a algo como esto:
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 todo funciona bien. Parece que React simplemente no logra diferenciar 'título del trabajo' y 'motivo de desempleo'.
Por favor dime qué estoy haciendo mal ...
javascript
reactjs
o01
fuente
fuente
data-reactid
en cada uno de los elementosMyInput
(oinput
, como se ve en DOM) antes y después delemployed
cambio?<div>
. Losdata-reactid
atributos parecen ser diferentes tanto en el div de envoltura como en el campo de entrada.job-title
la entrada obtiene iddata-reactid=".0.1.1.0.1.0.1"
, mientras que launemployment-reason
entrada obtiene iddata-reactid=".0.1.1.0.1.2.1"
unemployment-duration
?reactid
atributos son idénticos enjob-title
yunemployment-reason
, mientras que en el segundo ejemplo (con el intervalo diff) son diferentes.unemployment-duration
elreactid
atributo es siempre único.Respuestas:
Lo que probablemente está sucediendo es que React piensa que solo se agrega un
MyInput
(unemployment-duration
) entre los renders. Como tal,job-title
nunca se reemplaza porunemployment-reason
, que también es la razón por la que se intercambian los valores predefinidos.Cuando React hace la diferencia, determinará qué componentes son nuevos y cuáles son viejos en función de su
key
propiedad. Si no se proporciona dicha clave en el código, generará la suya propia.La razón por la que el último fragmento de código que proporcionas funciona es porque React esencialmente necesita cambiar la jerarquía de todos los elementos debajo del padre
div
y creo que eso desencadenaría una reproducción de todos los hijos (que es la razón por la que funciona). Si hubiera agregado elspan
en la parte inferior en lugar de en la parte superior, la jerarquía de los elementos anteriores no cambiaría, y esos elementos no se volverían a representar (y el problema persistiría).Esto es lo que dice la documentación oficial de React :
Debería poder solucionar este problema proporcionando un
key
elemento único usted mismo para el padrediv
o para todos losMyInput
elementos.Por ejemplo:
O
Ahora, cuando React haga la diferencia, verá que
divs
son diferentes y lo volverá a renderizar, incluidos todos sus elementos secundarios (primer ejemplo). En el segundo ejemplo, el diff será un éxitojob-title
yunemployment-reason
ya que ahora tienen diferentes claves.Por supuesto, puede utilizar las claves que desee, siempre que sean únicas.
Actualización de agosto de 2017
Para tener una mejor idea de cómo funcionan las claves en React, recomiendo encarecidamente leer mi respuesta a Comprender las claves únicas en React.js .
Actualización de noviembre de 2017
Esta actualización debería haberse publicado hace un tiempo, pero el uso de literales de cadena
ref
ahora está en desuso. Por ejemploref="job-title"
, ahora debería serref={(el) => this.jobTitleRef = el}
(por ejemplo). Consulte mi respuesta a la advertencia de obsolescencia usando this.refs para obtener más información.fuente
it will determine which components are new and which are old based on their key property.
- eso fue ... clave ... para mi comprensiónCambie la clave del componente.
El componente se desmontará y se montará una nueva instancia de Componente ya que la clave ha cambiado.
editar : Documentado sobre usted probablemente no necesite un estado derivado :
fuente
Úselo
setState
en su vista para cambiar laemployed
propiedad del estado. Este es un ejemplo del motor de renderizado React.fuente
Estoy trabajando en Crud para mi aplicación. Así es como lo hice Got Reactstrap como mi dependencia.
Algunos React Hooks ahí
fuente