繁体   English   中英

useEffect 挂钩内的 Graphql 订阅无法访问最新状态

[英]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为空。 我知道它设置正确,因为我在渲染的屏幕上显示它。 那么为什么doSomethingcurrentChannel为空的方式获得范围? 我怎样才能得到每个访问的最新鲜的状态时它来调用一个新的函数currentChannel每个时间next函数调用? 我尝试使用useState以及从 redux 存储/检索它,但没有任何效果。

实际上,它与涉及 javascript 闭包的所有异步操作有关:您的subscribe指的是初始doSomething (它在每次渲染时重新创建),它指的是初始currentChannel值。 文章有很好的例子供参考: https : //dmitripavlutin.com/react-hooks-stale-closures/

我们可以做什么? 我看到这里至少有两个动作:快速和基本。

  1. 我们可以利用useState返回完全相同(引用相同)的 setter 函数,它允许我们使用函数版本:
const doSomething = (thing) => {
  setCurrentChannel(currentChannelFromFunctionalSetter => {
    console.log(thing, currentChannelFromFunctionalSetter);
    return currentChannelFromFunctionalSetter;
  }
}
  1. 基本方法是利用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.

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