【问题标题】:React setstate not merging the old state into the new stateReact setstate 不会将旧状态合并到新状态
【发布时间】:2020-07-04 20:21:28
【问题描述】:

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

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]。

【问题讨论】:

    标签: javascript reactjs closures react-hooks lexical-closures


    【解决方案1】:

    这里的问题是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)})
    }
    
    }, [])
    

    【讨论】:

      【解决方案2】:

      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 的依赖项)

      【讨论】:

      • 是的,这就是我正在做的。合并有效,只是在第二次停止工作后。
      • @BTj84VvNNL2gh9GC 您没有使用 $timeseries 中的函数,您使用的是变量 _timeseries
      • 你应该使用一个函数,否则你可能会得到错误的值
      • 如果不是因为缺少 useEffect 依赖关系,那么它可以在没有功能的情况下工作吗?
      • 是的,但在你的情况下,我会使用一个函数,否则你将不得不取消订阅并重新订阅套接字。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-20
      • 1970-01-01
      • 2018-08-05
      • 1970-01-01
      相关资源
      最近更新 更多