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

使用Mobx Action获取任务时数据重复的原因排查

问题分析与解答

数据重复的原因

你的判断没错,React 18+的严格模式在开发环境下会自动执行两次空依赖的useEffect,这是React的调试机制,用来检测副作用代码是否能稳定运行。而你的fetchTasks方法里用this.tasks.push(...response.data.recordset),每次调用都会把后端返回的任务数组追加到现有tasks里,两次调用自然就导致数据重复了。

为什么没陷入无限循环

因为你的useEffect依赖是[](空数组),这意味着它只会在组件首次挂载时触发(严格模式下两次,但之后不会再触发)。哪怕TaskStore的tasks更新导致组件重渲染,useEffect因为没有监听任何依赖变化,也不会再次执行fetchTasks,所以不会出现无限循环的情况。

解决数据重复的几种方案

方案1:替换数组而非追加

修改fetchTasks里的赋值逻辑,直接替换整个tasks数组,而不是追加:

@action fetchTasks = async () => {
  try {
    const response: any = await axios.get('http://localhost:5000/test');
    // 直接替换数组,覆盖原有内容
    this.tasks = response.data.recordset;
  } catch (error) {
    console.error(error);
  }
};

这样就算fetchTasks被调用两次,第二次的结果会覆盖第一次的,不会出现重复数据。

方案2:添加加载状态避免重复请求

在TaskStore里加一个标记,判断是否已经加载过任务,避免重复发起请求:

class TaskStore {
  constructor() {
    makeAutoObservable(this);
  }
  tasks = [] as Task[];
  isTasksLoaded = false; // 新增加载状态标记

  @action fetchTasks = async () => {
    // 如果已经加载过任务,直接返回
    if (this.isTasksLoaded) return;
    try {
      const response: any = await axios.get('http://localhost:5000/test');
      this.tasks.push(...response.data.recordset);
      this.isTasksLoaded = true; // 标记为已加载
    } catch (error) {
      console.error(error);
    }
  };
}

方案3:了解React严格模式的行为(可选)

要记住React严格模式的两次执行只在开发环境存在,生产环境下useEffect只会执行一次。但还是推荐用前两种方案修复代码,不要依赖环境差异来规避问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 07:50:23