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

React Hook setValue在EventSource.onmessage中失效问题求助

解决SSE流拼接时React状态闭包问题

你遇到的是React的闭包陷阱:当toggleRequest执行时,getRealtimeData函数会捕获当时的currentResp状态值。后续组件因currentResp更新而重渲染时,这个函数内部的currentResp依然是最初捕获的旧值,导致每次拼接都用旧值累加,无法保留最新状态。

以下是两种可行的解决方法:

方法一:使用useState的函数式更新

useState的更新函数可以接收一个回调,回调参数是最新的状态值,完全避开闭包带来的旧值问题。修改setCurrentResp的调用逻辑:

function getRealtimeData(data) {
  const currentSSEText = data.choices[0].text;
  // 用函数式更新,prevState始终是最新的currentResp
  setCurrentResp(prevState => prevState + currentSSEText);
}

这种方式不需要额外变量,直接利用React内置的状态更新机制保证累加正确。

方法二:用useRef同步最新状态

如果需要在函数内部直接访问最新的currentResp值,可以用useRef来同步状态——ref的.current属性不受闭包影响,始终指向最新值:

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

// 定义状态和对应的ref
const [currentResp, setCurrentResp] = useState('');
const currentRespRef = useRef('');

// 每次currentResp更新时同步到ref
useEffect(() => {
  currentRespRef.current = currentResp;
}, [currentResp]);

// 在getRealtimeData中使用ref的值
function getRealtimeData(data) {
  console.log('Inside Function currentResp - ', currentRespRef.current);
  const currentSSEText = data.choices[0].text;
  setCurrentResp(currentRespRef.current + currentSSEText);
}

额外优化:避免重复创建SSE连接

每次调用toggleRequest都会新建EventSource,可能导致多个连接同时存在。可以用useRef保存连接实例,确保每次请求前关闭旧连接:

const sseRef = useRef(null);

const toggleRequest = () => {
  // 关闭之前的连接
  if (sseRef.current) {
    sseRef.current.close();
  }

  const url = 'https://somesseurl/sse';
  const sse = new EventSource(url);
  sseRef.current = sse;

  // ... 事件监听逻辑

  return () => {
    if (sseRef.current) {
      sseRef.current.close();
      sseRef.current = null;
    }
  };
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:09:27