我有訊息串列,并附加從套接字接收的實時訊息,從套接字插入一個物件,但之后它總是替換最后一個而不是插入新的。
const [chatList, setChatList] = useState(props.chatList ? props.chatList : []);
useEffect(() => {
const messageListener = (message) => {
console.log('message',message);
console.log('chatList',chatList);
if(message.conversation_id == props.conversation_id){
const updatedMsgs = [...chatList,message];
setChatList(updatedMsgs);
}
};
socket.on('myEventName', messageListener);
return () => {
socket.off('myEventName', messageListener);
};
}, [props.conversation_id]);
新訊息和訊息串列日志看起來像

uj5u.com熱心網友回復:
看起來像一個陳舊的chatList國家圍墻。使用功能狀態更新從之前的狀態更新,而不是在回呼范圍內關閉的狀態值,setChatList(list => [...list, message]);。
useEffect(() => {
const messageListener = (message) => {
console.log('message',message);
console.log('chatList',chatList);
if (message.conversation_id == props.conversation_id) {
setChatList(list => [...list, message]);
}
};
socket.on('myEventName', messageListener);
return () => {
socket.off('myEventName', messageListener);
};
}, [props.conversation_id]);
uj5u.com熱心網友回復:
由于Stale Closures在 Javascript 中,確實會發生此問題。
Hook 嚴重依賴 JavaScript閉包。這就是鉤子如此富有表現力和簡單的原因。但是閉包有時很棘手。
這是示例:
function DelayedCount() {
const [count, setCount] = useState(0);
function handleClickAsync() {
setTimeout(function delay() {
setCount(count 1);
}, 1000);
}
return (
<div>
{count}
<button onClick={handleClickAsync}>Increase async</button>
</div>
);
}
如果您快速單擊按鈕 2 次,那么它只會將計數增加 1,而不是 2。
每次單擊setTimeout(delay, 1000)安排delay()1 秒后的執行。delay()將變數捕獲count為 0。
兩者delay() closures(因為已經進行了 2 次點擊)都將狀態更新為相同的值:setCount(count 1) = setCount(0 1) = setCount(1)。
這一切都是因為delay() closure第二次點擊將過時的計數變數捕獲為 0。
為了解決這個問題,我們需要使用一種函式式的方式setCount(count => count 1)來更新計數狀態:
...
function handleClickAsync() {
setTimeout(function delay() {
setCount(count => count 1);
}, 1000);
}
...
現在按鈕確實按預期作業。
這是完整的文章,可以幫助您了解Stale Closures. 文章鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/358401.html
標籤:javascript 反应 反应钩子 使用效果 使用状态
上一篇:如何使用react-router-domv6渲染具有不同布局/元素的組件
下一篇:頁面加載時單擊觸發器()不起作用
