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

如何解决React状态设置中的竞态条件问题?

问题原因及解决方案

问题出在React闭包陷阱和状态更新的方式上:

  1. 调用loadingStream.subscribe时,回调函数捕获的data是当前组件渲染周期里的旧状态值——也就是初始状态中enableCopyToClipboard: true的版本。
  2. 当流返回数据触发回调时,执行setData({...data, output: ...})会把旧状态里的enableCopyToClipboard: true重新覆盖进去,直接冲掉了之前设置的false。

修复方案:使用函数式状态更新

把setData改成接收函数的形式,每次更新都会基于最新的状态快照修改,不再依赖闭包里的旧值:

// 加载流前重置状态
setData({ 
  ...data, 
  output: '',
  enableCopyToClipboard: false,
});

loadingStream(request).subscribe((response) => {
  resText.push(response.text);
  // 用函数式更新获取最新状态
  setData(prevData => ({ 
    ...prevData, 
    output: resText.join(''), 
  }));
});

补充优化:避免普通变量丢失数据

如果resText是组件内部的普通变量,组件重新渲染时会被重置,建议用useRef保存这个数组:

import { useState, useRef } from 'react';

// 组件内部
const [data, setData] = useState({
  input, 
  output: '', 
  enableCopyToClipboard: true,
});
const resTextRef = useRef([]);

// 监听流的代码
// 加载流前重置状态和缓存数组
setData(prev => ({
  ...prev,
  output: '',
  enableCopyToClipboard: false
}));
resTextRef.current = [];

loadingStream(request).subscribe((response) => {
  resTextRef.current.push(response.text);
  setData(prevData => ({ 
    ...prevData, 
    output: resTextRef.current.join(''), 
  }));
});

修改后,enableCopyToClipboard会保持你设置的false,直到你主动将其改回true。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 05:19:58