[英]React Functional Component Re-renders exponentially with array state change
我的一個功能組件有問題。 基本上,它在狀態中有一個消息數組; 當服務器發送一條新消息時,狀態應該通過將新消息推送到數組中來改變。 問題隨着陣列的增長而出現。 對於添加到數組中的每個項目,它都會以指數方式重新渲染。 例如。 對於數組中的一條消息,它呈現一次,對於兩條消息,它呈現兩次,對於三條消息,它呈現六次,等等......通常,這不會是一個大問題。 但是,在 useEffect 函數中,我進行了 api 調用,因此,我需要限制調用該函數的次數,並且還需要限制渲染。 這是組件的代碼,希望這一切都有意義。 謝謝您的幫助!
// Imports here...
let count = 0;
const Chat: React.FC<any> = ({ name, chatRoom, language }) => {
const [messages, setMessages] = useState<Array<MessageInterface>>([]);
const [message, setMessage] = useState<string>("");
const [users, setUsers] = useState<Array<string>>([]);
useEffect(() => {
socket = io(ENDPOINT, {
withCredentials: true,
extraHeaders: {
"my-custom-header": "abcd",
},
});
socket.on("connect", () => {
console.log(`I am now connected to the server with id: ${socket.id}`);
});
socket.emit("login", { name, chatRoom, language }, () => {});
// unmounting
return () => {
socket.emit("disconnectFromServer");
console.log("Disconnected from the server");
socket.off();
};
}, [name, chatRoom, language]);
useEffect(() => {
// ======== THIS IS THE FUNCTION THAT IS CALLED EXPONENTIALLY========
socket.on("message", (message: MessageInterface) => {
// This is where the api call would be
console.log(count);
count++;
setMessages([...messages, message]);
});
}, [messages]);
useEffect(() => {
socket.on("userJoin", (usersFromServer: Array<string>) => {
setUsers([...users, ...usersFromServer]);
});
}, [users]);
useEffect(() => {
socket.on("userLeave", (usersFromServer: Array<string>) => {
setUsers(usersFromServer);
});
}, [users]);
const sendMessage = (evt: React.KeyboardEvent<HTMLInputElement>) => {
evt.preventDefault();
if (message) {
socket.emit("sendMessage", message, () => setMessage(""));
}
};
return name && chatRoom ? (
<div id="chatOuterContainer">
<Users users={users} language={language} />
<div id="chatInnerContainer">
<InfoBar chatRoom={chatRoom} language={language} />
<Messages messages={messages} name={name} />
<Input
message={message}
setMessage={setMessage}
sendMessage={sendMessage}
language={language}
/>
</div>
</div>
) : (
<Redirect to="/" />
);
};
export default Chat;
當useEffect
清理時,您需要刪除消息偵聽器:
useEffect(() => {
const handler = (message: MessageInterface) => {
// This is where the api call would be
setMessages([...messages, message]);
});
socket.on("message", handler);
return () => {
socket.off("message", handler);
};
}, [messages]);
更好的方法是使用回調表單,以避免需要依賴外部messages
變量:
useEffect(() => {
const handler = (message: MessageInterface) => {
setMessages(messages => [...messages, message]);
});
socket.on("message", handler);
return () => {
socket.off("message", handler);
};
}, []);
useEffect(() => {
// ======== THIS IS THE FUNCTION THAT IS CALLED EXPONENTIALLY========
socket.on("message", (message: MessageInterface) => {
// This is where the api call would be
console.log(count);
count++;
setMessages([...messages, message]);
});
}, []);
socket.on('message',function) 應該只調用一次。 如果重復調用它,它將堆疊,而不是覆蓋。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.