Hi guys! Today I'd like to share a simple bug that I have found all the time when I first start learning React😅. Although the state is not updating on re-render, there is nothing related to virtual DOM or react-related concepts here. Instead this is a mistake that you might come across when coding in VanillaJS‼️
Goal
Let say you have a list of numerous items, each item has a button and increment its value when being clicked
My attempts
My state looks like this:
const [Test, setTest] = useState([
{
name: 'Eric',
value: 0
},
{
name: 'Frank',
value: 20
},
// and more....
])
Rendering part looks like this:
<div className="App">
{
Test.map((item, idx) => (
<button
key={idx}
onClick={(e) => {
e.preventDefault()
setTest((value) => {
value.find(element => element.name === item.name).value += 1
return value
})
}}
>
{
item.name + ': ' + item.value
}
</button>
))
}
</div>
Let's see...
Second attempt (90% of the time I make this mistake😷)
I've learnt that I should use an updater of setState, however it seems I have use it the wrong way🤒 I have mutated the state directly. Let's fix that by creating a new copy of the previous state.
//...
<button
key={idx}
onClick={(e) => {
e.preventDefault()
setTest((value) => {
let temp = value
temp.find(element => element.name === item.name).value += 1
return temp
})
}}
>
{
item.name + ': ' + item.value
}
</button>
//...
My Solution
The code that does the job:
//...
setTest((value) => {
let temp = [...value]
temp.find(element => element.name === item.name).value += 1
return temp
})
//...
Spread operator...
does help create a copy of the original state so that we don't mutate the original state, but this is just a one level shallow copy, it is still not recommended when dealing with nested object.
In our case, the element of state array is an object, which means the elements are reference, mutating them is still mutating the original state.
Moreover, nested state is not the intended use of React state, if you find yourself making a heavily nested state, you are not using it correctly!🦥
What do you think about it? Do you know any better solution? Did you come up with this problem and how do you solve it? Let me know in the comment!🙈
Cheers!
Top comments (0)