状态变量钩子不适用于 useEffect 回调
Posted
技术标签:
【中文标题】状态变量钩子不适用于 useEffect 回调【英文标题】:State variable hook not working with useEffect callback 【发布时间】:2020-09-21 20:46:15 【问题描述】:尝试在 react 功能组件中建立 websocket 连接,并使用钩子更新状态变量,如下所示 [Ref 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
的状态未被保留。它被覆盖了。
注意我也尝试将arr
传递给效果,就像这样,但这导致了无限循环。 [参考 2]。随着 arr 的更新,效果被调用...
)
, [arr])
举个更具体的例子,取三个 websocket 消息:
['a']
['b']
['c']
更新后每条消息的预期 arr
['a']
['a', 'b']
['a', 'b', 'c']
结果:
['a']
['b']
['c']
为什么arr
不与回调中的setArr
挂钩存储?为什么是空数组?
参考文献
-
WebSockets with functional components
https://github.com/facebook/react/issues/14066
【问题讨论】:
抱歉,我在这里找到了这个:***.com/questions/60152922/… 【参考方案1】:你有
useEffect( () =>
ws.current = new Websocket('ws://example.com:1234')
ws.current.onmessage = (m) =>
setArr([...arr, m])
)
, []) // Runs once at mount
确实,那里的效果挂钩在挂载时运行一次 - 这就是问题所在。当它运行时,附加的事件侦听器在触发时运行此行:
setArr([...arr, m])
使用该处理程序范围内的arr
的值。由于处理程序仅附加一次,因此在挂载时,arr
的值始终相同;初始状态,空数组。
改用回调:
setArr(arr => [...arr, m])
我还建议将ws
与const
一起声明,以避免意外创建全局变量(并且可能将其称为wsRef
而不是ws
,因此您不要混淆套接字的引用):
const wsRef = useRef(null)
【讨论】:
【参考方案2】:您可以尝试使用数组的先前状态:
ws.current.onmessage = (m) =>
setArr(prevState => [...prevState, m])
对于setState
,有两种处理变化的方法,第一种是给一个值作为参数,第二种是传递一个回调函数强>。它被称为更新函数,它提供状态的先前值。进一步了解setState
here。
【讨论】:
prevState
来自哪里?
@kmiklas 刚刚更新了我的解决方案来回答你的问题,希望能澄清一下。以上是关于状态变量钩子不适用于 useEffect 回调的主要内容,如果未能解决你的问题,请参考以下文章