javascript - qué - ¿Cómo forzar el montaje en los componentes React?
react meta tags (3)
Cambiar la clave del componente.
<Component key="1" />
<Component key="2" />
Component se desmontará y se montará una nueva instancia de Component ya que la clave ha cambiado.
editar : Documentado en usted probablemente no necesita estado derivado :
Cuando una clave cambia, React creará una nueva instancia de componente en lugar de actualizar la actual. Las claves se usan generalmente para listas dinámicas, pero también son útiles aquí.
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 cierto.
Cada vez que lo cambio a falso y se muestra la otra vista, solo se reinicia la
unemployment-duration
.
También
unemployment-reason
se llena previamente con el valor del
job-title
del
job-title
(si se dio un valor antes de que la condición cambiara).
Si cambio el marcado en la segunda rutina de representación 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 no logra diferenciar el "título del trabajo" y la "razón del desempleo".
Por favor dime que estoy haciendo mal ...
Lo que probablemente está sucediendo es que React piensa que solo se
MyInput
un
MyInput
(
unemployment-duration
) entre los renders.
Como tal, el
job-title
del
job-title
nunca se reemplaza con el
unemployment-reason
del
unemployment-reason
, que también es la razón por la cual se intercambian los valores predefinidos.
Cuando React haga la diferencia, determinará qué componentes son nuevos y cuáles son antiguos en función de su propiedad
key
.
Si no se proporciona dicha clave en el código, generará la suya.
La razón por la cual el último fragmento de código que proporcionó funciona es porque React esencialmente necesita cambiar la jerarquía de todos los elementos bajo el
div
principal y creo que eso desencadenaría una nueva representación de todos los elementos secundarios (por eso funciona).
Si hubiera agregado el
span
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 procesar (y el problema persistiría).
Esto es lo que dice la documentación oficial de React :
La situación se vuelve más complicada cuando los niños se barajan (como en los resultados de búsqueda) o si se agregan nuevos componentes al principio de la lista (como en las transmisiones). En estos casos en los que la identidad y el estado de cada niño deben mantenerse a través de los pases de representación, puede identificar de manera única a cada niño asignándole una clave.
Cuando React reconcilie a los niños con clave, se asegurará de que cualquier niño con clave se reordene (en lugar de golpearse) o se destruya (en lugar de reutilizarse).
Debería poder solucionar esto proporcionando usted mismo un elemento
key
único para el
div
principal o para todos los elementos
MyInput
.
Por ejemplo:
render(){
if (this.state.employed) {
return (
<div key="employed">
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div key="notEmployed">
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
O
render(){
if (this.state.employed) {
return (
<div>
<MyInput key="title" ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<MyInput key="reason" ref="unemployment-reason" name="unemployment-reason" />
<MyInput key="duration" ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Ahora, cuando React haga la diferencia, verá que los
divs
son diferentes y lo volverá a representar incluyendo a todos sus ''hijos'' (primer ejemplo).
En el segundo ejemplo, la diferencia será un éxito en
job-title
unemployment-reason
ya que ahora tienen claves diferentes.
Por supuesto, puede usar las teclas que desee, siempre que sean únicas.
Actualización de agosto de 2017
Para una mejor comprensión de cómo funcionan las claves en React, recomiendo leer mi respuesta a Comprender 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 en
ref
ahora está en desuso.
Por ejemplo,
ref="job-title"
ahora debería ser
ref={(el) => this.jobTitleRef = el}
(por ejemplo).
Consulte mi respuesta a la
Advertencia de desaprobación con this.refs
para obtener más información.
Use
setState
en su vista para cambiar la propiedad de estado
employed
.
Este es un ejemplo del motor de procesamiento React.
someFunctionWhichChangeParamEmployed(isEmployed) {
this.setState({
employed: isEmployed
});
}
getInitialState() {
return {
employed: true
}
},
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>
);
}
}