[英]Graphql subscriptions inside a useEffect hook doesn't access latest state
我正在构建一个基本的 Slack 克隆。 所以我有一个“房间”,它有多个“频道”。 用户订阅了 Room 中的所有消息,但如果新消息是用户当前频道的一部分,我们只会将它们添加到当前消息列表中
const [currentChannel, setCurrentChannel] = useState(null);
const doSomething = (thing) => {
console.log(thing, currentChannel)
}
useEffect(() => {
// ... Here I have a call which will grab some data and set the currentChannel
Service.joinRoom(roomId).subscribe({
next: (x) => {
doSomething(x)
},
error: (err: any) => { console.log("error: ", err) }
})
}, [])
我只是在这里展示一些代码来说明我的问题。 订阅在currentChannel
更新之前创建,这很好,因为我们想听一切,然后根据currentChannel
有条件地呈现。
我遇到的问题是,即使currentChannel
设置正确,因为在useEffect
钩子中定义next:
函数时它为空, doSomething
将始终记录currentChannel
为空。 我知道它设置正确,因为我在渲染的屏幕上显示它。 那么为什么doSomething
以currentChannel
为空的方式获得范围? 我怎样才能得到每个访问的最新鲜的状态时它来调用一个新的函数currentChannel
每个时间next
函数调用? 我尝试使用useState
以及从 redux 存储/检索它,但没有任何效果。
实际上,它与涉及 javascript 闭包的所有异步操作有关:您的subscribe
指的是初始doSomething
(它在每次渲染时重新创建),它指的是初始currentChannel
值。 文章有很好的例子供参考: https : //dmitripavlutin.com/react-hooks-stale-closures/
我们可以做什么? 我看到这里至少有两个动作:快速和基本。
useState
返回完全相同(引用相同)的 setter 函数,它允许我们使用函数版本:const doSomething = (thing) => {
setCurrentChannel(currentChannelFromFunctionalSetter => {
console.log(thing, currentChannelFromFunctionalSetter);
return currentChannelFromFunctionalSetter;
}
}
useRef
并将最新的doSomething
放在那里:const latestDoSomething = useRef(null);
...
const doSomething = (thing) => { // nothing changed here
console.log(thing, currentChannel)
}
latestDoSomething.current = doSomething; // happens on each render
useEffect(() => {
Service.joinRoom(roomId).subscribe({
next: (x) => {
// we are using latest version with closure on most recent data
latestDoSomething.current(x)
},
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.