I have an object looking like this:
categories : [
{
name: "General Information",
rows: [
{
information1 : "",
information2 : "",
}
]
}
]
And I am displaying the rows content using a loop like this:
{formData?.categories?.map(c => (
<div>
{c.name}
{c.rows.map((row) => (
<div>
<input value={field.information1} />
<textarea value={field.information2}></textarea>
<button onClick={() => addRow(c.name)}>Add Row here</button>
</div>
))}
</div>
))}
When I press one of these buttons (that should add a row to rows array) the formData state does update, but the displayed data does not.
function addRow(category) {
const updatedFormData = formData
for (const cat of updatedFormData.categories) {
if (cat.name === category) {
cat.rows.push({
information1 : "test",
information2 : "this is a test"
})
}
}
setFormData(updatedFormData)
}
In the addRow function, create a copy of formData before updating it
function addRow(category) {
const updatedFormData = {...formData};
// Make changes to updatedFormData
setFormData(updatedFormData)
}
We need to create a copy before updating to let react know that the state has changed.
Consider this scenario,
const obj1 = {a : 1, b: 2};
const obj2 = obj1;
obj2.b = 12;
console.log(obj1 === obj2); // true
obj1 and obj2 point to the same object reference. Even if we changed the value of b, the reference has not changed. Similarly, when we updated the categories of formData without creating a copy, the reference had not changed, and react has no way to know that the state has been updated. So we create a new object and copy the contents of formData to it and then update the copy and set the state with the copy.
From the official docs:
State can hold any kind of JavaScript value, including objects. But you shouldn’t change objects that you hold in the React state directly. Instead, when you want to update an object, you need to create a new one (or make a copy of an existing one), and then set the state to use that copy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With