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

React使用EventSource监听事件后useState更新出现累积重复日志如何解决

问题产生原因
  • 副作用未限制执行时机且未清理:原代码的useEffect没有传入第二个依赖参数,这会导致每次组件重渲染时都会重新执行useEffect逻辑,重复调用connect新建EventSource连接、注册新的heartBeat事件监听器。同时旧的连接没有被关闭、旧的监听器没有被移除,每次heartBeat事件触发时,历史累计注册的所有监听器都会同时执行,直接表现就是日志数量逐次递增。
  • 闭包捕获旧值问题:handleHeartBeat定义在组件内部,每一轮渲染都会生成新的函数实例,闭包会捕获当前渲染周期的x值。不同轮次注册的监听器拿到的都是注册时的旧x值,因此输出的数值序列会是历史累积的旧值组合。
修复方案

核心是限制连接仅初始化一次,做好副作用清理,同时避免闭包旧值问题:

  1. 给useEffect添加空依赖数组,保证仅在组件挂载时初始化一次EventSource连接
  2. 在useEffect的清理函数中添加连接关闭、监听器移除逻辑,避免内存泄漏和重复监听
  3. 若需要打印最新的x值,可在setX的函数式回调中打印,或单独用useEffect监听x变化打印

修复后代码示例:

import { useState, useEffect, useRef } from 'react';

export default function ComponentA(props) {
    const [x, setX] = useState(0);
    // 用useRef存储EventSource实例,跨渲染周期保持引用
    const esRef = useRef(null);

    useEffect(() => {
        const connect = (url) => {
            esRef.current = new EventSource(url, { withCredentials: false });
            esRef.current.addEventListener('heartBeat', handleHeartBeat);
        };

        const handleHeartBeat = (event) => {
            setX((prevX) => {
                const newX = prevX + 1;
                // 在setX的函数式回调中打印可拿到最新的x值
                const currentdate = new Date(); 
                const datetime = `${currentdate.getHours()}:${currentdate.getMinutes()}:${currentdate.getSeconds()}`;
                console.log("time =", datetime + "; x =", newX);
                return newX;
            });
        };

        connect("http://localhost:18200/events/agg/dotusd");

        // 清理函数:组件卸载时关闭连接、移除监听器
        return () => {
            if (esRef.current) {
                esRef.current.removeEventListener('heartBeat', handleHeartBeat);
                esRef.current.close();
                esRef.current = null;
            }
        };
    }, []); // 空依赖数组,仅组件挂载时执行一次

    return (
        <div>
            <ComponentB key='1' x={x} />
        </div>
    );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 20:27:02