我正在使用 React 和 socket 構建一個實時聊天應用程式來掌握基礎知識。每當用戶發送訊息時,所有其他用戶都會收到兩次相同的訊息。
我正在使用 react-router 來提供加入“頁面”和聊天“頁面”。
function App() {
return (
<div className="App">
<Router>
<Routes>
<Route path="/" element={<Join />} />
<Route path="/chat/:name" element={<Chat />} />
</Routes>
</Router>
</div>
);
}
在聊天頁面中,在用戶之間呈現訊息的地方,我正在使用useEffect鉤子,但是我很難完全理解它。
function Chat () {
const [messages, addMessage] = useState([{
username: "chatbot",
time: new Date(),
message: "Welcome to the chatroom ??"
}]);
const location = useLocation();
const [currentUser, updateUser] = useState(() => {
const user = location.pathname.split('/chat/')[1];
socket.emit("join_chat", {
username: user
})
return user;
});
useEffect(() => {
socket.on("receive_message", (data) => {
console.log('received message');
addMessage(prevMessages => {
return [...prevMessages, {
username: data.username,
time: new Date(),
message: data.message
}]
})
})
}, [socket])
const sendMessage = (e) => {
e.preventDefault();
socket.emit("send_message", {
message: currentMessage,
username: currentUser,
});
每次發送訊息時,控制臺日志都會在接收端運行兩次。
據我了解,該鉤子允許我們定義一些在 DOM 發生更改時將運行的代碼,所以我不確定這種更改在哪里發生了兩次?
我也不確定為什么首先socket.on應該住在里面useEffect。如果useEffect僅在重新渲染后立即呼叫,它如何仍然通過套接字接收每條訊息?
uj5u.com熱心網友回復:
根據您的描述,聽起來您正在將應用程式渲染為一個React.StrictMode組件,該組件運行某些生命周期方法和功能兩次,以幫助檢測無意/意外的副作用。
效果運行兩次,無意/意外的副作用是代碼為事件添加了兩個事件處理程式"receive_message"。
useEffect當組件卸載或socket依賴項更改時,該掛鉤缺少回傳清理函式以取消訂閱套接字/訊息事件。
useEffect(() => {
const handleMessage = (data) => {
console.log('received message');
addMessage(prevMessages => {
return [...prevMessages, {
username: data.username,
time: new Date(),
message: data.message
}]
});
};
socket.on("receive_message", handleMessage);
return () => {
socket.off("receive_message", handleMessage);
};
}, [socket]);
據我了解,該鉤子允許我們定義一些代碼,這些代碼將在 DOM 發生更改時運行
該useEffect鉤子允許您定義一些代碼,這些代碼將在組件出于任何原因呈現時作為副作用運行。React 組件重新渲染的原因是 (1) 更新了本地狀態,(2) 更新了 React prop,(3) 重新渲染了父組件(出于任何相同的原因)。
我也不確定為什么首先
socket.on應該住在里面useEffect。
React 組件中的“渲染”方法被認為是一個純函式。React Function 組件的整個函式體是“render”方法。訂閱外部資源被認為是“不純”的操作,即它是一種副作用,并且應該只作為常規 React 組件生命周期的一部分進行訂閱。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/527796.html
