[英]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.