【问题标题】:Graphql subscriptions inside a useEffect hook doesn't access latest stateuseEffect 挂钩中的 Graphql 订阅不会访问最新状态
【发布时间】:2019-12-22 15:27:36
【问题描述】:

我正在构建一个基本的 Slack 克隆。所以我有一个“房间”,里面有多个“频道”。用户订阅了 Room 中的所有消息,但如果新消息是用户当前 Channel 的一部分,我们只会将它们添加到当前消息列表中

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 为空的方式限定范围呢?每次调用next 函数时,我怎样才能让它每次访问currentChannel 的最新状态时调用一个新函数?我尝试了 useState 以及从 redux 存储/检索它,但没有任何效果。

【问题讨论】:

    标签: reactjs apollo react-apollo apollo-client


    【解决方案1】:

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

    我们能做什么?我在这里看到至少 2 个动作:快速和基本的。

    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) 
        },
    

    【讨论】:

    • 这非常有用。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2022-01-21
    • 2022-01-17
    • 2019-09-23
    • 2021-11-15
    • 1970-01-01
    • 2019-12-27
    • 2021-02-11
    • 2020-08-17
    相关资源
    最近更新 更多