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

将数组或对象传入React useMemo等依赖数组是否合理?

将对象/数组传入React依赖数组是否合理?

直接把对象或数组丢进useMemo的依赖数组完全不合理——因为React用Object.is()做依赖比较,而引用类型(对象、数组)每次渲染都会生成新的引用,哪怕内容完全没变,Object.is()的结果也会是false,导致useMemo失去缓存作用,内部代码每次渲染都重新执行。

下面分场景给出合理的处理方案:

场景1:对象仅包含原始值(字符串、数字、布尔等)

这种情况直接解构出具体属性传入依赖数组即可。React会逐个比较原始值,只有当属性值真的发生变化时,才会触发useMemo重新计算。

示例代码:

// 不推荐:每次渲染user都是新对象,useMemo每次都执行
const userName = useMemo(() => `${user.firstName} ${user.lastName}`, [user]);

// 推荐:解构原始值,仅当firstName/lastName变化时重新计算
const userName = useMemo(() => `${user.firstName} ${user.lastName}`, [user.firstName, user.lastName]);

场景2:对象包含非原始值(数组、嵌套对象、函数)

需要根据值的生成逻辑和稳定性来处理:

子场景2.1:非原始值是稳定的(不会随渲染变化)

如果这个值是组件外部定义的常量,或者已经用useMemo/useCallback缓存过,直接把缓存后的引用传入依赖数组即可:

// 外部稳定数组
const fixedTags = ['react', 'javascript'];

function MyComponent() {
  const filteredTags = useMemo(() => fixedTags.filter(tag => tag.includes('react')), [fixedTags]);
}

// 组件内用useMemo缓存嵌套对象(空依赖确保只初始化一次)
const userProfile = useMemo(() => ({
  basic: { name: 'Alice', age: 30 },
  hobbies: ['reading', 'hiking']
}), []);

const profileSummary = useMemo(() => `${userProfile.basic.name} likes ${userProfile.hobbies.join(', ')}`, [userProfile]);

子场景2.2:非原始值是动态生成的(随渲染变化)

如果这个值是基于其他状态动态生成的,要么拆解它的底层原始依赖,要么先用useMemo缓存这个非原始值本身:

// 不推荐:每次渲染生成新数组,useMemo失效
const activeUsers = useMemo(() => {
  return users.filter(u => u.isActive);
}, [users]); // users是父组件传入的数组,每次父组件渲染可能传新引用

// 推荐方案1:拆解底层原始依赖
// 假设users是基于父组件的searchText和allUsers生成的,直接用这两个原始依赖
const activeUsers = useMemo(() => {
  return allUsers.filter(u => u.isActive && u.name.includes(searchText));
}, [allUsers, searchText]);

// 推荐方案2:先缓存非原始值(用唯一标识判断是否真变化)
const stableUsers = useMemo(() => users, [users.id, users.length]); // 用数组的唯一ID或长度判断内容是否变更
const activeUsers = useMemo(() => stableUsers.filter(u => u.isActive), [stableUsers]);

子场景2.3:函数作为依赖

组件内定义的函数每次渲染都会重新创建,此时用useCallback缓存函数,再把缓存后的函数传入依赖数组:

// 不推荐:每次渲染生成新的formatUser函数,useMemo每次执行
const formattedUser = useMemo(() => formatUser(user), [user, formatUser]);

// 推荐:用useCallback缓存函数(空依赖表示函数内部不依赖组件状态)
const formatUser = useCallback((user) => {
  return `${user.name} (${user.age})`;
}, []);

const formattedUser = useMemo(() => formatUser(user), [user, formatUser]);

总结

  • 绝对不要直接把未缓存的引用类型丢进依赖数组,会彻底废掉useMemo的缓存能力;
  • 原始值优先解构传入;非原始值要么提前缓存,要么拆解其底层的原始依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 09:00:56