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

React StrictMode下useEffect重复执行及清理函数实现咨询

解决React StrictMode下useEffect重复执行导致的重复调用问题

问题根源

你的代码核心问题有两个:

  1. Chat组件的useEffect依赖数组为空,既无法响应新的用户消息,又会在StrictMode开发环境下被强制执行两次;
  2. 状态更新和服务调用没有做幂等处理,导致重复执行时重复添加消息、调用服务。

解决方案

1. 修正useEffect依赖并添加幂等控制

通过useRef记录已处理过的用户消息,即使StrictMode触发两次useEffect,也能跳过重复执行的逻辑;同时补全依赖数组,确保新消息能触发处理。

修改后的Chat组件代码:

const Chat = (props) => {
  const { messages, lastUserMessage, setChatBotMessages, callService } = props;
  // 用ref记录已处理的消息,避免重复执行
  const processedMsgRef = useRef(null);

  useEffect(() => {
    if (lastUserMessage && lastUserMessage.trim() && lastUserMessage !== processedMsgRef.current) {
      // 标记当前消息为已处理
      processedMsgRef.current = lastUserMessage;
      // 完整更新状态,保留原有字段
      setChatBotMessages((prev) => ({
        ...prev,
        messages: [...prev.messages, lastUserMessage]
      }));
      // 调用服务
      callService(lastUserMessage);
    }
  }, [lastUserMessage, setChatBotMessages, callService]); // 补全所有依赖

  return <div>{messages.map((msg, idx) => <span key={idx}>{msg} </span>)}</div>;
};

2. 完善服务调用后的状态处理

在callService中更新状态时,建议清空lastUserMessage,从根源上避免同一消息被重复触发处理:

const callService = (lastUserMessage) => {
  // 模拟异步服务调用(实际项目中替换为真实请求)
  setChatBotMessages((prev) => ({
    ...prev,
    messages: [...prev.messages, "New response from service"],
    lastUserMessage: "" // 清空用户消息,防止重复处理
  }));
};

3. 优化初始状态传递

ChatBot组件的初始状态可以直接解构chatBotConfig,避免冗余代码:

const [chatBotMessages, setChatBotMessages] = useState({ ...chatBotConfig });

关键说明

  • 依赖数组必须完整:useEffect的依赖要包含所有用到的外部变量,否则会出现闭包过期问题,且无法响应新的用户输入;
  • useRef做幂等标记:useRef的内容不会随组件渲染重置,适合记录状态类的标记,用来过滤重复执行的逻辑;
  • 状态更新需保留完整结构:更新状态时使用...prev保留未修改的字段,避免丢失lastUserMessage等状态数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 15:14:52