Descargo de responsabilidad
El estado anidado en React es un diseño incorrecto
Lee esta excelente respuesta .
Razonamiento detrás de esta respuesta:
SetState de React es solo una conveniencia incorporada, pero pronto te das cuenta de que tiene sus límites. El uso de propiedades personalizadas y el uso inteligente de forceUpdate le brinda mucho más. p.ej:
class MyClass extends React.Component {
myState = someObject
inputValue = 42
...
MobX, por ejemplo, abandona el estado por completo y utiliza propiedades observables personalizadas.
Use Observables en lugar de estado en React components.
Hay otra forma más corta de actualizar cualquier propiedad anidada.
this.setState(state => {
state.nested.flag = false
state.another.deep.prop = true
return state
})
En una linea
this.setState(state => (state.nested.flag = false, state))
nota: Aquí está el operador de coma ~ MDN , vea aquí en acción (Sandbox) .
Es similar a (aunque esto no cambia la referencia de estado)
this.state.nested.flag = false
this.forceUpdate()
Para la sutil diferencia en este contexto entre forceUpdate
y setState
ver el ejemplo vinculado.
Por supuesto, esto está abusando de algunos principios básicos, ya que state
deberían ser de solo lectura, pero dado que descarta inmediatamente el estado anterior y lo reemplaza por un estado nuevo, está completamente bien.
Advertencia
A pesar de que el componente que contiene el estado se actualizará y volverá a mostrar correctamente ( excepto este problema ) , los accesorios no se propagarán a los niños (consulte el comentario de Spymaster a continuación) . Solo use esta técnica si sabe lo que está haciendo.
Por ejemplo, puede pasar un accesorio plano modificado que se actualiza y pasa fácilmente.
render(
//some complex render with your nested state
<ChildComponent complexNestedProp={this.state.nested} pleaseRerender={Math.random()}/>
)
Ahora, aunque la referencia para complexNestedProp no cambió ( shouldComponentUpdate )
this.props.complexNestedProp === nextProps.complexNestedProp
el componente se volverá a generar cada vez que se actualice el componente principal, que es el caso después de llamar this.setState
o this.forceUpdate
en el elemento primario.
Efectos de mutar el estado
Usar el estado anidado y mutar el estado directamente es peligroso porque diferentes objetos pueden contener (intencionalmente o no) diferentes (más antiguas) referencias al estado y no necesariamente saber cuándo actualizar (por ejemplo, cuando se usa PureComponent
o si shouldComponentUpdate
se implementa para regresar false
) O son destinado a mostrar datos antiguos como en el ejemplo a continuación.
Imagine una línea de tiempo que se supone que representa datos históricos, mutar los datos debajo de la mano dará como resultado un comportamiento inesperado, ya que también cambiará los elementos anteriores.
De todos modos, aquí puede ver que Nested PureChildClass
no se reenvió debido a que los accesorios no se propagan.