为什么在循环内设置 useState 会执行不同的操作?
Why does setting useState inside a loop perform differently?
有人可以向我解释以下代码片段吗?为什么 handleClick() 不能正常工作(只设置了 newData 的 1 或 2 个数据属性)而 handleClick2() 可以正常工作。
我猜问题是循环引起的(因为这是唯一的区别),但为什么循环会导致这种效果?
沙盒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
原因是:
setNewData
是异步函数。当你调用 setNewData
时,React 会以某种方式将其回调函数推送到事件循环中,然后在主线程为空时在主线程中回调它。当 setNewData
回调函数在 main 中调用时 field
是 test4
因为 for (field of fields)
同步函数。 ==> 只有 setNewData(oldState => ({...oldState, data4: 'test'}))
调用了 4 次。
您可以在 setNewData
回调函数中记录 field
并查看它的值。
for (field of fields) {
console.log(field)
setNewData(oldState => {
console.log(field)
return { ...oldState, [field]: "test" }
})
}
有人可以向我解释以下代码片段吗?为什么 handleClick() 不能正常工作(只设置了 newData 的 1 或 2 个数据属性)而 handleClick2() 可以正常工作。
我猜问题是循环引起的(因为这是唯一的区别),但为什么循环会导致这种效果?
沙盒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
原因是:
setNewData
是异步函数。当你调用 setNewData
时,React 会以某种方式将其回调函数推送到事件循环中,然后在主线程为空时在主线程中回调它。当 setNewData
回调函数在 main 中调用时 field
是 test4
因为 for (field of fields)
同步函数。 ==> 只有 setNewData(oldState => ({...oldState, data4: 'test'}))
调用了 4 次。
您可以在 setNewData
回调函数中记录 field
并查看它的值。
for (field of fields) {
console.log(field)
setNewData(oldState => {
console.log(field)
return { ...oldState, [field]: "test" }
})
}