Soy nuevo en React y tengo un problema. Obtuve un objeto grande que contendrá mucha lógica para la aplicación que estoy tratando de construir.
Basado en este objeto, estoy tratando de representar campos de entrada y también actualizar los registros correspondientes en el objeto. Tengo un Codesandbox con la configuración de mi problema aquí .
Obtuve mi componente de 'nivel superior' que contiene el objeto y lo pasa a sus hijos:
import "./styles.css"; import { useState } from "react"; import Content from "./Content"; export default function App() { const [formDocument, setFormDocument] = useState({ document: { content: { sections: [ { additionalFields: true, destroyable: false, key: "personalDetails", moveable: false, fields: [ { fieldType: "text", key: "name", linkedFieldsKey: "name" }, { fieldType: "text", key: "emailAddress", linkedFieldsKey: "emailAddress" } ] } ], records: [{ key: "1", values: ["Tim", "tim@gmail.com"] }] } } }); const updateDocument = (e) => { //how do I update the corresponding records for the inputfields? console.log("inputfield is updated"); }; return ( <div className="App"> <h1>Hello CodeSandbox</h1> <Content {...formDocument} updateDoc={(e) => updateDocument(e)} /> </div> ); } Ahora tengo un niño que usa el objeto formDocument llamado Content.jsx y quiero actualizar los records correspondientes en el objeto formDocument . Este es el Content.jsx :
export default function Content({ updateDoc, ...formDocument }) { return ( <div> <input style={{ display: "block", marginTop: "10px" }} type="text" value={formDocument.document.content.records[0].values[0]} onChange={(e) => updateDoc(e)} /> <input style={{ display: "block", marginTop: "10px" }} type="text" value={formDocument.document.content.records[0].values[1]} onChange={(e) => updateDoc(e)} /> </div> ); }¿Cómo actualizo los registros correctos sin hacer una función para todos y cada uno de los campos de entrada?
Creo que deberías escupir a los Estados, pero el código para esto es el siguiente: -
import "./styles.css"; import { useState } from "react"; import Content from "./Content"; export default function App() { const [formDocument, setFormDocument] = useState({ document: { content: { sections: [ { additionalFields: true, destroyable: false, key: "personalDetails", moveable: false, fields: [ { fieldType: "text", key: "name", linkedFieldsKey: "name" }, { fieldType: "text", key: "emailAddress", linkedFieldsKey: "emailAddress" } ] } ], records: [{ key: "1", values: ["Tim", "tim@gmail.com"] }] } } }); const updateDocument = (e, index) => { //how do I update the corresponding records for the inputfields? let new_document = {...formDocument}; new_document['document']['content']['records'][0]['values'][index]=e.target.value; setFormDocument(new_document); }; return ( <div className="App"> <h1>Hello CodeSandbox</h1> <Content {...formDocument} updateDoc={updateDocument} /> </div> ); }El contenido.js
export default function Content({ updateDoc, ...formDocument }) { return ( <div> {formDocument.document.content.records[0].values.map((elem, i) => ( <input style={{ display: "block", marginTop: "10px" }} type="text" value={elem} onChange={(e) => updateDoc(e,i) } /> ))} </div> ); }Al actualizar un objeto/matriz en React, debe asegurarse de actualizarlo con un elemento "nuevo". Para hacer eso, podrías crear una copia como esta:
const arrayCopy = [...array] const objectCopy = {...object}Al actualizar el estado usando el mismo objeto o matriz, React no sabrá que ese elemento ha sido actualizado.
Entonces, por ejemplo, si tiene esto en el estado:
const [document, setDocument] = useState({ users: [ { name: 'Peter', email: 'hi@peter.com' }, { name: 'Michael', email: 'hi@michael.com' }, ] })Luego, seguiría estos pasos para actualizar el estado correctamente:
// Create a copy of the object in the state let updatedObject = {...document} // Update it as needed let newUsers = [...document.users] newUsers[1].name = 'Manolo' const updatedObject = { ...document, users: [...newUsers] } // Update the state with a copy of the new object // For doing so, I'd pass a function callback setUsers(() => ({ ...updatedObject }))Eso debería hacer volver a renderizar su componente y ver los cambios.
También reorganizaría un poco el estado. Divídalo cuando sea necesario, puede usar más de una variable de estado. Eso te ayudará a localizar los errores y depurarlos mejor. También mejora la legibilidad y le permitirá escribir mejor código.