Reputation: 2328
Can someone explain the following code snippet to me please? Why does handleClick() not work properly (only 1 or 2 of the data properties of newData are set) whereas handleClick2() works properly.
I am guessing the problem is due to the loop (since that is the only difference), but why does a loop cause this effect?
sandbox link: https://codesandbox.io/s/restless-surf-u9i5s?file=/src/App.js:0-969
import React, { useState, useEffect } from "react";
import "./styles.css";
const App = () => {
const [newData, setNewData] = useState({
data1: '',
data2: '',
data3: '',
data4: ''
})
const handleClick = () => {
let fields = ['data1', 'data2', 'data3', 'data4']
let field
for (field of fields) {
setNewData(oldState => ({...oldState, [field]: 'test'}))
}
}
const handleClick2 = () => {
setNewData(oldState => ({...oldState, data1: 'test'}))
setNewData(oldState => ({...oldState, data2: 'test'}))
setNewData(oldState => ({...oldState, data3: 'test'}))
setNewData(oldState => ({...oldState, data4: 'test'}))
}
useEffect(() => {
console.log('State: ' + JSON.stringify(newData))
}, [newData])
return (
<div className="App">
<button onClick={handleClick}>Click</button>
<button onClick={handleClick2}>Click2</button>
</div>
);
}
export default App
Upvotes: 0
Views: 28
Reputation: 3488
The reason is:
setNewData
is async function. When you call setNewData
somehow React will push its callback function in event loop then call it back in main thread when the main thread empty. When setNewData
callback function is call in main field
is test4
because for (field of fields)
sync function. ==> only setNewData(oldState => ({...oldState, data4: 'test'}))
is call 4 times.
You can log the field
inside of setNewData
callback function and see the value of it.
for (field of fields) {
console.log(field)
setNewData(oldState => {
console.log(field)
return { ...oldState, [field]: "test" }
})
}
Upvotes: 1