Digamos que tengo dos Componentes. Al padre se le pasa un objeto como propiedad, que luego copia en el almacén de datos local. Tiene una función para actualizar esta tienda local, que se transmite a un niño. Aquí está mi componente principal:
const Parent = ({stuff}) => { const store = { stuff: Object.assign({}, stuff); } const updateStuff = (thing, property) => store.stuff[thing].property = thing; return <Child stuff={stuff} updateStuff={updateStuff} /> } El componente secundario tiene una estructura similar: hace una copia de stuff y muta su copia de stuff en un onChange de <input> . Luego pasa su propia copia actualizada de las cosas a la función updateStuff que recibió, para mutar la copia de la propiedad del padre. Aquí está el Niño.
const Child = ({stuff, updateStuff}) => { const stuff = { thing1: Object.assign({}, stuff.thing1), thing2: Object.assign({}, stuff.thing2) } const setProp = event => { const update = event.target.value; stuff.thing1.prop = update; updateStuff(thing1, stuff.thing1.prop) } return ( <div> <input id="thing1" onChange={setProp} /> <input id="thing1" onChange={setProp} /> </div> ) } Tenga en cuenta que he usado Object.assign para, básicamente, clonar el accesorio de stuff o sus propiedades secundarias, según lo requiera el caso. La razón de esto: un accesorio React es de solo lectura y, por lo tanto, necesito crear un clon para realizar cambios antes de devolverlo para mutar el estado de la aplicación (no se muestra aquí)/
Ahora, esto funciona en el componente secundario: setProp muta la propiedad correcta de stuff , confirmada al iniciar sesión en la consola. Sin embargo, cuando el método llega a updateTeam , aparece un mensaje de error: Error de tipo Uncaught TypeError: Cannot assign to read only property 'side' of object '#<Object>'
Sin embargo, ambos componentes usan el mismo principio: no estoy mutando el accesorio, sino que estoy mutando un clon almacenado localmente del accesorio. ¿Por qué funciona esto para Child, pero no para Parent?
Object.assign solo hace una copia superficial de la propiedad Object.assign Reference . Para hacer una verdadera copia profunda del accesorio (y deshacerse del error), puede hacer una copia profunda con newStuff: JSON.parse(JSON.stringify(stuff)) . ¡Me alegro de que esto haya ayudado!
La verdadera razón detrás de esto se da en un ejemplo:
let original = { name: 'Test', nestedObj: { (...some properties) } }En el ejemplo anterior, la propiedad del objeto original 'nombre' es una copia nueva, pero el objeto anidado sigue siendo una referencia al original. De esta manera, cuando intenta editar la parte del objeto anidado, hace referencia al original y grita que es inmutable.
Intente cambiar const para let sus copias locales