You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React循环渲染组件出现DOM重叠问题的原因排查及代码示例

问题解决:WebSocket子组件循环渲染时DOM重叠

问题根源

循环渲染子组件时出现DOM内容重叠,核心原因是共享WebSocket实例的消息监听被覆盖:

  • 所有子组件共用同一个WebSocket连接,每次直接给socket.onmessage赋值都会覆盖之前的回调函数,最终只有最后一个子组件的回调生效,导致所有组件显示同一份数据。
  • 未在组件卸载时清理监听,旧的回调可能继续触发,引发不必要的状态更新。
  • 父组件使用数组索引idx作为key,数据变动时React可能错误复用组件,加剧渲染异常。

解决方案

1. 用事件监听替代直接赋值onmessage

通过addEventListener添加消息监听,允许多个回调并存;同时在组件卸载时移除监听,避免内存泄漏。

2. 匹配组件专属数据

在消息回调中校验返回数据的number是否与当前组件的num一致,确保只更新当前组件的状态。

3. 优化父组件的key值

用唯一标识(如allot.number)替代数组索引作为key,保证React正确识别组件身份。

修正后的代码

子组件

import { useContext, useEffect, useState } from "react";
import { WebsocketContext } from "./Wsconnection";
import React from "react";

const Allotments = ({ num }) => {
  const [isReady, socket] = useContext(WebsocketContext);
  const [allotdata, setAllotdata] = useState({});

  useEffect(() => {
    if (!isReady) return;

    // 定义专属消息处理函数
    const handleMessage = (e) => {
      const data = JSON.parse(e.data);
      // 只处理当前组件对应的num的数据
      if (data.type === "get_allotment_details" && data.number === num) {
        const altdata = data.alloted_details[0];
        setAllotdata({ customer: altdata.prq__customer__name });
      }
    };

    // 发送请求
    socket.send(JSON.stringify({ type: "get_allotment_details", number: num }));
    // 添加事件监听
    socket.addEventListener("message", handleMessage);

    // 清理函数:移除监听,避免内存泄漏
    return () => {
      socket.removeEventListener("message", handleMessage);
    };
  }, [isReady, num, socket]);

  return (
    <div>
      <h5>{allotdata?.customer}</h5>
    </div>
  );
};
export default Allotments;

父组件

import React from "react";
import Allotments from "./Allotments";

const init_alloted = JSON.parse(document.getElementById("reporting").dataset.alloted) || [];

export const Alloted = () => {
  const allots = init_alloted.map((allot) => {
    // 使用唯一的allot.number作为key,避免组件复用异常
    return (
      <div key={allot.number}>
        <Allotments num={allot.number} />
      </div>
    );
  });

  return <div className="col">{allots}</div>;
};

内容的提问来源于stack exchange,提问作者Harish Ahuja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 10:17:22