繁体   English   中英

State 变量挂钩不适用于 useEffect 回调

[英]State variable hook not working with useEffect callback

尝试在 React 功能组件中建立 websocket 连接,并使用钩子更新 state 变量,如 [参考文献 1] 所示:

export default function foo() {
    const [ arr, setArr ] = useState([])
    ws = useRef(null)

    useEffect( () => {
        ws.current = new Websocket('ws://example.com:1234')
        ws.current.onmessage = (m) => {
            setArr([...arr, m])
        })
    }, []) // Runs once at mount
}

arr的 state 没有保留。 它被覆盖了。

注意我也试过将arr传递给效果,就像这样,但这导致了无限循环。 [参考文献 2]。 随着 arr 的更新,效果被称为...

        })
    }, [arr])
}

举个更具体的例子,取三个 websocket 消息:

['a']
['b']
['c']

更新后每条消息的预期 arr

['a']
['a', 'b']
['a', 'b', 'c']

结果:

['a']
['b']
['c']

为什么arr不与回调中的setArr挂钩一起存储? 为什么它是一个空数组?

参考

  1. 具有功能组件的 WebSockets
  2. https://github.com/facebook/react/issues/14066

你有

useEffect( () => {
    ws.current = new Websocket('ws://example.com:1234')
    ws.current.onmessage = (m) => {
        setArr([...arr, m])
    })
}, []) // Runs once at mount

事实上,那里的效果挂钩在挂载上运行一次——这就是问题所在。 当它运行时,附加的事件侦听器在被触发时运行以下行:

setArr([...arr, m])

为该处理程序使用 scope 中的arr值。 由于处理程序仅附加一次,在挂载时, arr的值始终相同; 初始 state,空数组。

请改用回调:

setArr(arr => [...arr, m])

我还建议用const声明ws ,以避免意外创建全局变量(并且可能将其wsRef而不是ws ,这样您就不会混淆套接字的 ref ):

const wsRef = useRef(null)

您可以尝试使用数组的前一个 state 代替:

ws.current.onmessage = (m) => {
   setArr(prevState => [...prevState, m])
}

对于setState有两种方法可以处理更改,第一种是给一个值作为参数,第二种是传递回调 function 它称为更新程序 function,它提供 state 的先前值。在此处进一步了解setState

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM