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

React中SSE更新状态未触发重渲染的原因及解决方案

问题根因

React 对引用类型(数组、对象)的状态变更判断依赖引用相等性:只有当状态的内存引用地址发生变化时,React 才会判定状态更新,进而触发重渲染。
你的代码中,setPromptsResultsArray 的更新函数直接修改了原状态数组 prevPromptsResultsArray 的内部项,最终返回的还是原数组本身,数组的引用地址完全没有变化,React 检测不到状态变更,因此不会触发重渲染。只有当 prompt 状态变化、组件因其他原因重渲染时,之前直接修改的数组值才会被渲染到页面上,这就是你观察到“B的更新要等A再次变化才显示”的核心原因。

规范修复方案

React 状态更新的核心规则是:永远不要直接修改原状态,所有针对引用类型状态的更新,必须返回一个全新的引用副本。

  1. 修复SSE消息回调中的状态更新逻辑,替换为返回新数组副本的写法:
newBackendEventSource.addEventListener('message', (e) => {
  const data = JSON.parse(e.data);
  setPromptsResultsArray((prevPromptsResultsArray) => {
    const index = prevPromptsResultsArray.length - data.counter - 1
    // 创建原数组的浅拷贝,不直接修改原数组
    const nextArray = [...prevPromptsResultsArray]
    // 替换对应位置的项,嵌套对象也要创建新副本,不直接修改原对象
    nextArray[index] = {
      ...nextArray[index],
      isLoading: false,
      URIs: [data.uri]
    }
    // 返回全新引用的数组,React可检测到变更触发渲染
    return nextArray
  });
});
  1. 补充useEffect清理逻辑,避免内存泄漏:
    你当前的useEffect只在prompt变化时创建新的SSE连接,但没有关闭旧连接的逻辑,会导致重复创建连接、重复接收消息。需要在useEffect中返回清理函数,在依赖变化、组件卸载时关闭旧连接:
useEffect(() => {
  const newBackendEventSource = new EventSource(url, {withCredentials: false})
  // 原有事件监听逻辑保持不变
  newBackendEventSource.addEventListener('open', () => {
    console.log('SSE opened!');
  });
  // ... 其余open/error/close/message监听逻辑不变

  // 新增清理逻辑
  return () => {
    newBackendEventSource.close()
  }
}, [prompt]);
  1. 可选优化:将状态初始值移到组件外,或传入useState的初始化函数,避免组件每次渲染都重复创建初始数组对象,减少不必要的性能开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 00:57:25