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

为何传入的依赖已变化,useMemo却未重新执行?

问题解答

你的理解是否正确?

你对useMemo的核心逻辑理解是对的:它会缓存回调函数的计算结果,仅当依赖项数组中的值发生引用变化时,才会重新执行回调并更新缓存结果。

你的实现方式存在的问题

  1. 冗余的状态存储:useMemo本身已经可以缓存过滤后的结果,没必要再将其存入useState——这会多一次状态更新,可能触发额外的组件重渲染,完全是画蛇添足。
  2. 依赖项无法检测到内部变化:你的TaskStore用Mobx管理状态,当通过setCompleted修改数组中任务的completed属性时,数组本身的引用并没有改变(你只是修改了数组内对象的属性,没有替换整个数组)。而React的useMemo依赖项对比的是引用值,所以它会认为TaskStore.tasks没有变化,不会重新执行过滤逻辑,导致incompleteTasks始终是旧值。

正确的实现方式

结合Mobx的特性,推荐两种更合理的写法:

方式1:在Store中定义计算属性

直接在TaskStore里用Mobx的computed定义过滤后的任务列表,组件中直接使用这个计算属性,Mobx会自动追踪依赖并在数据变化时更新:

import { makeAutoObservable, computed } from "mobx";

class TaskStore {
  public tasks: Task[] = [];
  constructor() {
    makeAutoObservable(this);
  }

  @action setCompleted = (task: Task, completed: number) => {
    const index = this.tasks.indexOf(task);
    if (index !== -1) {
      this.tasks[index].completed = !!completed;
    }
  };

  // 定义计算属性,自动过滤未完成任务
  get incompleteTasks() {
    return this.tasks.filter(task => !task.completed);
  }
}

组件中用observer包裹,直接使用计算属性:

import { observer } from "mobx-react-lite";

const TaskList = observer(() => {
  const { incompleteTasks } = TaskStore;

  return (
    <div>
      {/* 渲染未完成任务列表 */}
      {incompleteTasks.map(task => (
        <div key={task.id}>{task.name}</div>
      ))}
    </div>
  );
});

方式2:在observer组件内直接过滤

如果不想在Store里加计算属性,也可以直接在组件内过滤,只要用observer包裹组件,Mobx会追踪tasks数组内的属性变化,自动触发重渲染和过滤:

import { observer } from "mobx-react-lite";

const TaskList = observer(() => {
  const incompleteTasks = TaskStore.tasks.filter(task => !task.completed);

  return (
    <div>
      {incompleteTasks.map(task => (
        <div key={task.id}>{task.name}</div>
      ))}
    </div>
  );
});

总结

  • useMemo的基础理解没问题,但你的实现不符合Mobx的最佳实践,且存在依赖检测失效的问题。
  • 结合Mobx时,优先用observer包裹组件+Store计算属性/组件内直接过滤的方式,让Mobx负责状态追踪和重渲染触发,避免手动用useMemo+useState的冗余写法。

内容的提问来源于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 12:15:24