React 组件因渲染而导致内存使用量增加?是否有冲突或内存泄漏?

问题描述 投票:0回答:1

这是我的组件,发生的情况是我连接到我的 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 崩溃。

内存问题是否源于我错误地渲染组件?

reactjs websocket
1个回答
0
投票
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);
}, []);


© www.soinside.com 2019 - 2024. All rights reserved.