Estoy tratando de organizar mi estado usando propiedades anidadas como esta:
this.state = {
someProperty: {
flag:true
}
}
Pero actualizar estado como este,
this.setState({ someProperty.flag: false });
no funciona ¿Cómo se puede hacer esto correctamente?
javascript
reactjs
ecmascript-6
setstate
Alex Yong
fuente
fuente
Respuestas:
Para
setState
un objeto anidado, puede seguir el siguiente enfoque, ya que creo que setState no maneja las actualizaciones anidadas.La idea es crear un objeto ficticio realizar operaciones en él y luego reemplazar el estado del componente con el objeto actualizado
Ahora, el operador de propagación crea solo una copia anidada de nivel del objeto. Si su estado está altamente anidado como:
Puede configurar State utilizando el operador de propagación en cada nivel como
Sin embargo, la sintaxis anterior se vuelve fea a medida que el estado se anida cada vez más y, por lo tanto, le recomiendo que use el
immutability-helper
paquete para actualizar el estado.Vea esta respuesta sobre cómo actualizar el estado con
immutability helper
.fuente
someProperty
y estamos modificando esothis.setState((prevState) => ({nested: {...prevState.nested, propertyToSet: newValue}})
un poco tedioso ......prevState,
en el último ejemplo, solo túsomeProperty
y sus hijosPara escribir en una línea
fuente
this.state
inmediatamente despuéssetState
y espere que tenga el nuevo valor. Versus llamandothis.state
dentrosetState
. ¿O también hay un problema con este último que no me queda claro?this.state
despuéssetState
. Además, no estamos pasandothis.state
asetState
. El…
operador difunde propiedades. Es lo mismo que Object.assign (). github.com/tc39/proposal-object-rest-spreadthis.setState(currentState => { someProperty: { ...currentState.someProperty, flag: false} });
podría permitir evitar este problema?A veces las respuestas directas no son las mejores :)
Version corta:
este codigo
debería simplificarse como algo así
Versión larga:
Actualmente no debería querer trabajar con estado anidado en React . Porque React no está orientado a trabajar con estados anidados y todas las soluciones propuestas aquí parecen piratas informáticos. No usan el marco pero luchan con él. Sugieren escribir código no tan claro con el propósito dudoso de agrupar algunas propiedades. Por lo tanto, son muy interesantes como respuesta al desafío, pero prácticamente inútiles.
Imaginemos el siguiente estado:
¿Qué sucederá si cambia solo un valor de
child1
? React no volverá a representar la vista porque usa una comparación superficial y verá que laparent
propiedad no cambió. Por cierto, mutar el objeto de estado directamente se considera una mala práctica en general.Por lo tanto, debe volver a crear todo el
parent
objeto. Pero en este caso nos encontraremos con otro problema. Reaccionar pensará que todos los niños han cambiado sus valores y los volverá a representar a todos. Por supuesto, no es bueno para el rendimiento.Todavía es posible resolver ese problema escribiendo una lógica complicada,
shouldComponentUpdate()
pero preferiría detenerme aquí y usar una solución simple de la versión corta.fuente
Descargo de responsabilidad
la respuesta a tu miseria - mira el ejemplo aquí
Hay otra forma más corta de actualizar cualquier propiedad anidada.
En una linea
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)
Para la sutil diferencia en este contexto entre
forceUpdate
ysetState
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.
Ahora, aunque la referencia para complexNestedProp no cambió ( shouldComponentUpdate )
el componente se volverá a generar cada vez que se actualice el componente principal, que es el caso después de llamar
this.setState
othis.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 sishouldComponentUpdate
se implementa para regresarfalse
) O son destinado a mostrar datos antiguos como en el ejemplo a continuación.De todos modos, aquí puede ver que
Nested PureChildClass
no se reenvió debido a que los accesorios no se propagan.fuente
state
completamente y utiliza propiedades observables personalizadas . React'ssetState
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 deforceUpdate
le brinda mucho más. Use Observables en lugar de estado en React components.this.forceUpdate()
o implementar específicosshouldComponentUpdate
.Si está utilizando ES2015, tiene acceso a Object.assign. Puede usarlo de la siguiente manera para actualizar un objeto anidado.
Combina las propiedades actualizadas con las existentes y utiliza el objeto devuelto para actualizar el estado.
Editar: se agregó un objeto vacío como objetivo a la función de asignación para asegurarse de que el estado no esté mutado directamente como señaló Carkod.
fuente
fuente
property
contiene varias propiedades anidadas, la primera las eliminará, la segunda no. codesandbox.io/s/nameless-pine-42thuHay muchas bibliotecas para ayudar con esto. Por ejemplo, usando immutability-helper :
Usando lodash / fp set:
Usando lodash / fp merge:
fuente
lodash
, probablemente quiera probar_.cloneDeep
y establecer el estado para que sea la copia clonada.lodash/fp
, así que no tenemos que preocuparnos por las mutaciones.merge
oset
funciones en lodash / fp además de la sintaxis?this.setState(newState)
a los métodos lodash / fp. Otro problema es que lodash.set
(no fp) tiene un orden diferente de argumentos que me hizo tropezar por un tiempo.Utilizamos Immer https://github.com/mweststrate/immer para manejar este tipo de problemas.
Acabo de reemplazar este código en uno de nuestros componentes
Con este
Con immer manejas tu estado como un "objeto normal". La magia ocurre detrás de escena con objetos proxy.
fuente
Aquí hay una variación en la primera respuesta dada en este hilo que no requiere ningún paquete adicional, bibliotecas o funciones especiales.
Para establecer el estado de un campo anidado específico, ha establecido todo el objeto. Hice esto creando una variable
newState
y difundiendo el contenido del estado actual primero usando el operador de propagación ES2015 . Luego, reemplacé el valor dethis.state.flag
con el nuevo valor (ya que establecíflag: value
después de extender el estado actual en el objeto, elflag
campo en el estado actual se anula). Luego, simplemente configuro el estado desomeProperty
minewState
objeto.fuente
Aunque la anidación no es realmente cómo debe tratar un estado de componente, a veces es algo fácil para la anidación de un solo nivel.
Para un estado como este
Un método reutilizable que he usado se vería así.
luego simplemente pasa el nombre del obj para cada anidamiento que desea abordar ...
fuente
Usé esta solución.
Si tiene un estado anidado como este:
puede declarar la función handleChange que copia el estado actual y la reasigna con valores cambiados
aquí el html con el oyente de eventos
fuente
Crea una copia del estado:
hacer cambios en este objeto:
ahora actualiza el estado
fuente
Aunque usted preguntó sobre un estado del componente React basado en clases, el mismo problema existe con useState hook. Peor aún: useState hook no acepta actualizaciones parciales. Entonces, esta pregunta se volvió muy relevante cuando se introdujo el gancho useState.
He decidido publicar la siguiente respuesta para asegurarme de que la pregunta cubra escenarios más modernos en los que se usa el gancho useState:
Si tienes:
puede establecer la propiedad anidada clonando la actual y aplicando parches a los segmentos requeridos de los datos, por ejemplo:
O puede usar la biblioteca Immer para simplificar la clonación y el parcheo del objeto.
O puede usar la biblioteca Hookstate (descargo de responsabilidad: soy un autor) para simplemente administrar por completo los datos de estado complejos (locales y globales) y mejorar el rendimiento (lea: no se preocupe por la optimización del renderizado):
obtener el campo para representar:
establecer el campo anidado:
Aquí está el ejemplo de Hookstate, donde el estado está anidado profunda / recursivamente en una estructura de datos en forma de árbol .
fuente
Otras dos opciones aún no mencionadas:
fuente
Para hacer las cosas genéricas, trabajé en las respuestas de @ ShubhamKhatri y @ Qwerty.
objeto de estado
controles de entrada
método updateState
setState como la respuesta de @ ShubhamKhatri
setState como la respuesta de @ Qwerty
Nota: estos métodos anteriores no funcionarán para matrices
fuente
Me tomo muy en serio las preocupaciones ya expresadas en torno a la creación de una copia completa del estado de su componente. Dicho esto, sugeriría encarecidamente a Immer .
Esto debería funcionar
React.PureComponent
(es decir, las comparaciones de estado superficial por React), ya queImmer
utiliza inteligentemente un objeto proxy para copiar eficientemente un árbol de estado arbitrariamente profundo. Immer también es más seguro para los tipos de letra en comparación con bibliotecas como Immutability Helper, y es ideal para usuarios de Javascript y Typecript por igual.Función de utilidad mecanografiada
fuente
fuente
obj
es solo una referencia al estado, por lo que a través de él estás mutando elthis.state
objeto realEncontré que esto funciona para mí, tener un formulario de proyecto en mi caso donde, por ejemplo, tiene una identificación y un nombre y prefiero mantener el estado de un proyecto anidado.
¡Házmelo saber!
fuente
Algo como esto podría ser suficiente,
fuente
Sé que es una vieja pregunta, pero aún quería compartir cómo lo logré. Asumiendo el estado en el constructor se ve así:
Mi
handleChange
función es así:Y asegúrese de nombrar las entradas en consecuencia:
fuente
Hago actualizaciones anidadas con una búsqueda reducida :
Ejemplo:
Las variables anidadas en estado:
La función:
Utilizar:
fuente
Este es mi estado inicial
El gancho o puede reemplazarlo con el estado (componente de clase)
El método para handleChange
Método para establecer el estado con estados anidados
Finalmente esta es la entrada que uso
fuente
Si está utilizando formik en su proyecto, tiene una manera fácil de manejar estas cosas. Aquí está la forma más fácil de hacer con formik.
Primero establezca sus valores iniciales dentro del atributo formik initivalues o en la reacción. estado
Aquí, los valores iniciales se definen en estado de reacción
definir valores iniciales iniciales para el campo formik dentro del
initiValues
atributo formikHaga una consola para verificar el estado actualizado en
string
lugar deboolean
lasetFieldValue
función formik para establecer el estado o vaya con la herramienta de depuración de reacción para ver los cambios dentro de los valores de estado formik.fuente
prueba este código:
fuente
someProperty
y después de que se ejecute el código anterior, soloflag
quedará la propiedadVi lo siguiente en un libro:
pero no estoy seguro si es correcto ...
fuente