簡體   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