![](/img/trans.png)
[英]Why React js receive multiple answer from server with Socket.io?
[英]Socket.io and React: Proper way too receive data from server and set state in a component?
嘗試運行一個基本的聊天應用程序,但在發送消息時遇到過度重新呈現的問題。 這是客戶端的適用代碼:
const [chatMessages, setChatMessages] = useState([]);
const sendChat = (e) => {
socket.emit("sendMessage", e.target.elements.message.value);
}
useEffect(() => {
socket.on("receiveMessage", (chatMessage) => {
setChatMessages([...chatMessages, chatMessage]);
console.log(chatMessages);
});
}, [chatMessages]);
return (
{chatMessages.map((message) => <p>{message}</p>)}
)
然后,在服務器上:
io.on("connection", (socket) => {
socket.on("sendMessage", (chatMessage) => {
console.log("message sent");
io.to(roomId).emit("receiveMessage", chatMessage);
});
}
當我這樣做時,消息已成功發送和接收,但會導致它發生很多次(控制台):
[]
[]
[{...}]
[{...}]
(2) [{...}, {...}]
在第三條消息中,這是記錄的內容。 到第六條或第七條消息時,整個頁面都停止了,因為它記錄了大約 100 次。
我嘗試了以下方法:
在useEffect()
中有一個空的依賴數組。 這確實修復了重新渲染,但引入了一個新問題。 最新消息是唯一保存並替換最后一條消息的消息,因此您一次只能看到一條消息。
將其全部從useEffect()
中取出。 這只會使問題惡化,並導致每條消息的重新呈現次數更多。
任何幫助,將不勝感激。 謝謝!
當chatMessages
state 更新但不清除它們時,您正在創建套接字事件處理程序。 如果您編輯您的代碼或組件重新呈現等......然后添加另一個套接字事件處理程序。 多個處理程序將開始堆疊並排隊多個意外的 state 更新。
此外,由於 React state 更新是異步處理的,您無法在更新排隊后立即記錄 state 並期望看到更新后的 state。為此使用單獨的useEffect
掛鈎。
添加useEffect
清理 function 以刪除事件處理程序,並在處理程序回調中重新包含更新的chatMessages
state 數組。
useEffect(() => { const handler = (chatMessage) => { setChatMessages([...chatMessages, chatMessage]); } socket.on("receiveMessage", handler); return () => socket.off("receiveMessage", handler); }, [chatMessages]);
添加一個useEffect
清理 function,刪除依賴項以便效果在組件安裝時運行一次,並使用功能性 state 更新從回調附件中的先前 state 而不是初始 state 正確更新。
useEffect(() => { const handler = (chatMessage) => { setChatMessages(chatMessages => [...chatMessages, chatMessage]); } socket.on("receiveMessage", handler); return () => socket.off("receiveMessage", handler); }, []);
在這兩者之間,第二個選項是更優的解決方案,但你選擇哪個是你的決定。
要記錄聊天消息chatMessages
更新:
useEffect(() => {
console.log(chatMessages);
}, [chatMessages]);
由於您依賴於chatMessages
,每次chatMessages
更改時,它都會創建一個新的偵聽器。 這就是為什么當收到更多消息時它變得越來越慢。
你可以做兩件事:
useEffect
方法中本地維護chatMessages
。 您可以展開該數組,然后使用展開的數組調用setChatMessages
。 執行此操作時,您可以刪除chatMessages
對useEffect
的依賴性,並且仍然擁有所有消息。 作為一種好的做法,您應該返回一個 function,它將在組件卸載時刪除事件偵聽器。 const [chatMessages, setChatMessages] = useState([]); const sendChat = (e) => { socket.emit("sendMessage", e.target.elements.message.value); } useEffect(() => { let localMessages = []; const callback = (chatMessage) => { localMessages = [...localMessages, chatMessage]; setChatMessages(localMessages); console.log(localMessages); }; socket.on("receiveMessage", callback); return () => { socket.off("receiveMessage", callback); } }, []); return ( {chatMessages.map((message) => <p>{message}</p>)} )
useRef
來存儲值。 但是,當值更改時,這不會觸發 UI 的重新呈現,這可能不是您想要的。 所以這可能不是一個好的選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.