我具有以下设置状态的功能:
const [study, setStudy] = useState(defaultState)
const setValue = (section, key, value) => {
setStudy({...study, [section]: {...study[section], [key]: value}})
}
但是由于某种原因,它会继续覆盖现有状态,我在做什么错了?
我这样调用函数:
setValue('company', 'name', 'test')
setValue('property', 'state', 'test2')
setValue('property', 'address', 'test3')
数据结构:
const defaultState: StudyData = {
client: {},
company: {},
property: {},
study: {}
}
答案 0 :(得分:2)
我认为问题在于您破坏的学习价值仍然是旧版本(被记忆)。所有setValue
调用之间都是相同的,因此前两个setValue
调用实际上什么也不做。如果这是您的情况,则解决此问题的最佳方法是为setStudy
提供回调函数。给定值器的任何函数都将获取状态的绝对最新版本作为参数。像这样尝试:
setStudy((latestStudy) => {
return {
...latestStudy,
[section]: {...latestStudy[section], [key]: value}
}
});
答案 1 :(得分:1)
在处理多个状态更新事件时,React的标准行为是对它们进行批处理。状态更新方法不会立即更新组件的状态,React只是将更新放入队列中,以便在事件处理完成后稍后进行处理。在事件结束时,所有更改都一起刷新,您看不到中间状态。
使用批处理时,当执行最终的set-state事件时,无法回忆起prevState已更新(异步),这就是为什么最终状态似乎只反映了上一个事件所做的更改的原因。
将回调函数用作setStudy
方法的第一个参数将有助于您返回中间状态并避免出现批处理问题。更新器功能将循环遍历所有合并的状态,并将其与先前的组件状态进行浅合并。这样可以确保我们在最终到达最终更新之前,接收所有状态更新并使用所有中间状态。
const setValue = (section, key, value) => {
setStudy(study => {
return {
...study,
[section]: { ...study[section], [key]: value }
};
});
};