这是我的组件,发生的情况是我连接到我的 websocket 并监听来自服务器的传入消息并显示它们。每当我的消息列表超过 10 条消息时,我就会对第一个元素进行切片并添加新元素。我的数组确认长度不超过10个元素,并且每条消息的数据相当小。
import React, { useEffect, useState, useRef } from "react";
const ws = new WebSocket("ws://localhost:8000?uid=React");
export default function Discord () {
const [messages, setMessages] = useState([]);
ws.addEventListener("message", data => {
if (messages.length >= 10) {
setMessages(arr => arr.slice(1,arr.length).concat(JSON.parse(data.data)));
} else setMessages([...messages, JSON.parse(data.data)]);
});
return(
<div class="bg-gray-900 rounded-lg h-full w-full">
<div class="relative overflow-y-scroll scroll-smooth xl:h-4/5 h-5/6 top-0 w-full">
<div class="absolute">
<MessageList messages={messages}/>
</div>
</div>
</div>
);
};
function MessageList ({ messages }) {
const messagesEndRef = useRef(null)
useEffect(() => {
messagesEndRef.current.scrollIntoView()
});
return (
<ul class="">
{messages.map(message => <DiscordMessage messageData={message}/>)}
<div ref={messagesEndRef}/>
</ul>
)
}
我也可以确认是这个组件,因为我已经删除了它并监控了内存使用情况,它稳定在 600mb 左右。每当我启用此组件时,它就会攀升至 6GB,然后通常会使 Firefox 崩溃。
内存问题是否源于我错误地渲染组件?
ws.addEventListener("message", data => {
if (messages.length >= 10) {
setMessages(arr => arr.slice(1,arr.length).concat(JSON.parse(data.data)));
} else setMessages([...messages, JSON.parse(data.data)]);
});
它位于组件的主体中,因此每次
Discord
渲染时,您都会添加一个额外的事件侦听器。这些永远不会被清理干净。您需要将其移至 useEffect 中,并添加清理功能。
此外,您当前正在调用 setMessages 之前检查
messages.length
。这需要您将 messages
放入效果的依赖数组中。更好的方法是将其移至对 setMessages
的调用中,然后它就不需要位于依赖项数组中。
useEffect(() => {
const onMessage = (data) => {
setMessages((arr) => {
if (arr.length >= 10) {
return arr.slice(1, arr.length).concat(JSON.parse(data.data));
} else {
return [...arr, JSON.parse(data.data)];
}
});
};
ws.addEventListener("message", onMessage);
return () => ws.removeEventListener("message", onMessage);
}, []);