React setstate 不将旧状态合并到新状态

React setstate not merging the old state into the new state

根据许多示例,这应该有效:

const [_timeseries, $timeseries] = useState({hi:'lol'})

useEffect(() => {

socket.on('plot', e => {
 let keyname = Object.keys(e)[0]
 $timeseries({..._timeseries, [keyname] : value)})
}

}, [])

console.log(_timeseries) // here results in the initial state, not the set state

第一次合并时,它起作用了。 但是一旦有另一个键名的新事件进入,它就会再次取代整个事件。 不是使用 [keyname] 添加新密钥,而是替换旧的 [keyname]。

useState 挂钩为您提供了一个用新值完全替换状态(不合并它)的函数:https://reactjs.org/docs/hooks-state.html

However, unlike this.setState in a class, updating a state variable always replaces it instead of merging it.

您可以将 setState 与函数一起使用并自行合并:

$timeseries((old) => ({...old, [keyname] : value)}))

如果你在没有函数的情况下使用它,它可能具有旧值(因为你没有将它指定为 useEffect 的依赖项)

这里的问题是closures

分配给 useEffect 的回调关闭了 _timeseries 在它的词法范围内的初始值,并且它从未更新过。

要修复它,您需要使用 the functional useState,它在其回调中使用最新状态:

const [_timeseries, $timeseries] = useState({hi:'lol'})

useEffect(() => {
socket.on('plot', e => {
 let keyname = Object.keys(e)[0]
 $timeseries(timeSeries => {...timeseries, [keyname] : value)})
}

}, [])