This is a simplified example of some code I have.
I have a some state, that stores an array of objects
const [characters,setCharacters] = useState([
{
val:1,
bool:false
},
{
val:2,
bool:false
},
{
val:3,
bool:false
},
])
I want to update one of the bool
's to true. I then do
setCharacters(prev => {
prev[2].bool = true
return prev
})
But it doesn't work. Can anyone explain why?
CodePudding user response:
You need to set a new reference. That is how react detect updates for state variables which are objects.
setCharacters(prev => {
let prev2=[...prev]
prev2[2] ={ ...prev2[2], bool : true};
return prev2;
})
Above code, creates a new reference for the array and the object at 2
index.
CodePudding user response:
This will generate too many re-renders
because you have called to times set function which is actually componentDidUpdate().
In this case you have to use useEffect hook to wrap the second set function.
import { useEffect, useState } from "react"
const Test = () => {
const [characters,setCharacters] = useState([
{
val:1,
bool:false
},
{
val:2,
bool:false
},
{
val:3,
bool:false
},
])
// useEffect - component life-cycle method (componentDidUpdate)
useEffect(() => {
// your update functionality
setCharacters(prev => {
prev[2].bool = true
return prev
})
},[]); // empty dependency array to render the UI only at first
return (
<div>
{
characters.map((item, i) => {
return (
<div key={i}>
<p>{item.val}</p>
<p>{item.bool ? "true":"false"}</p>
</div>
)
})
}
</div>
)
}
export default Test;
I this way you can update the state while page first time rendering.
Your Initial Value for prev[2] was false; But see in image below that your prev[2] = true as you were expecting.
Here is the output on browser: