Javascript React功能组件随阵列状态的变化以指数方式重新渲染
我的一个功能组件出现问题。基本上,它在状态中有一个消息数组;当服务器发送新消息时,状态应该通过将新消息推送到数组中来改变。随着阵列的增长,问题也随之出现。对于添加到数组中的每个项,它都以指数方式重新渲染。例如当数组中有一条消息时,它渲染一次,对于两条消息,它渲染两次,对于三条消息,它渲染六次,等等。。。通常情况下,这不是什么大问题。但是,在useEffect函数中,我正在进行api调用,因此,我需要限制调用该函数的次数,并且还需要限制渲染。下面是组件的代码,希望这一切都有意义。谢谢你的帮助Javascript React功能组件随阵列状态的变化以指数方式重新渲染,javascript,arrays,reactjs,typescript,Javascript,Arrays,Reactjs,Typescript,我的一个功能组件出现问题。基本上,它在状态中有一个消息数组;当服务器发送新消息时,状态应该通过将新消息推送到数组中来改变。随着阵列的增长,问题也随之出现。对于添加到数组中的每个项,它都以指数方式重新渲染。例如当数组中有一条消息时,它渲染一次,对于两条消息,它渲染两次,对于三条消息,它渲染六次,等等。。。通常情况下,这不是什么大问题。但是,在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]);
更好的方法是使用回调表单,以避免依赖外部消息变量:
useEffect(() => {
const handler = (message: MessageInterface) => {
setMessages(messages => [...messages, message]);
});
socket.on("message", handler);
return () => {
socket.off("message", handler);
};
}, []);
当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]);
更好的方法是使用回调表单,以避免依赖外部消息变量:
useEffect(() => {
const handler = (message: MessageInterface) => {
setMessages(messages => [...messages, message]);
});
socket.on("message", handler);
return () => {
socket.off("message", handler);
};
}, []);
socket.on'message',函数只能调用一次。如果您重复调用它,它将堆叠,而不是覆盖
socket.on'message',函数只能调用一次。如果您反复调用它,它将堆叠,而不是覆盖。嘿,非常感谢,您的解决方案看起来与上述类似。删除第二个参数中的调用有助于修复它!嘿,非常感谢,看起来您的解决方案与上述类似。删除第二个参数中的调用有助于修复它!