banner
我是老王

我是老王

我用尽全力,过着平凡的生活!
github
twitter
email
follow
discord user

React性能优化 | 别再让你的 React 页面卡成PPT了!useMemo必学

做过 React 项目的应该都遇到过这种情况:开发时页面丝般顺滑,但一上线数据量大了就卡得要死。点个按钮要等三秒,比我家猫起床都慢。

别急着甩锅给后端,今天说个 React 里经常被忽视但很有用的东西 —— useMemo

这玩意儿名字听起来像 "有记忆",其实就是组件的省电模式。

useMemo 是什么#

想象你有个同事,每次问他复杂问题都要算半天。关键是每问一次他就重算一遍,哪怕数据压根没变。

useMemo就像给这个同事装了个记忆:上次算过的结果记着呢,你要不要直接用?

本质就是缓存计算结果,只要依赖没变就直接返回旧结果,不重复计算。

语法长这样:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

只有当ab改了才重新算,否则直接返回上次的结果。

什么时候用#

1. 计算很重的时候#

比如处理5000条订单数据做排序、过滤、统计。这种操作每次都跑风扇都要起飞,而组件一天要渲染几十次。

const processedData = useMemo(() => {
  return heavyProcess(orders); // 耗时操作
}, [orders]); // 只有orders变了才重算

这样就从每次渲染都算变成只算一次。

2. 给子组件传对象或数组#

子组件用了React.memo但还是一直重渲染?很可能是因为传过去的 prop 每次都是新的引用。

比如这样:

// 每次渲染都创建新数组,哪怕内容一样
<MyComponent filters={[{ type: "active" }]} />

解决方法:

const stableFilters = useMemo(() => [{ type: "active" }], []);
<MyComponent filters={stableFilters} />;

这样对象地址就不变了,React.memo才能正常工作。

3. 作为其他 Hook 的依赖项#

const config = { userId, theme };

useEffect(() => {
  fetchUserData(config);
}, [config]); // 问题来了!

每次渲染config都是新对象,useEffect就会重复触发。

解决:

const config = useMemo(() => ({ userId, theme }), [userId, theme]);

useEffect(() => {
  fetchUserData(config);
}, [config]);

现在只有userIdtheme变了config才更新。

useMemo vs useCallback#

这两个容易搞混:

Hook缓存的是啥?使用场景
useMemo一个值复杂计算、对象 / 数组、作为依赖
useCallback一个函数本身防止函数变化导致子组件重渲染
// useMemo:缓存"计算结果"
const total = useMemo(() => items.reduce(sum), [items]);

// useCallback:缓存"函数本身"
const handleClick = useCallback(() => doSomething(id), [id]);

常见坑点#

依赖项写错#

useMemo(() => expensive(), [{}]); // 每次都是新对象!
useMemo(() => expensive(), [[]]); // 每次都是新数组!

确保依赖项是稳定的值。

滥用 useMemo#

不是所有计算都要缓存。如果只是简单的a + b,用useMemo反而浪费。

React 官方说过:过早优化是万恶之源。先找到性能瓶颈再用useMemo

总结#

什么时候用:

  • 计算很重
  • 传给memo子组件的对象 / 数组
  • 作为其他Hook的依赖项

记住:它是瑞士军刀,不是创可贴。

页面卡了别急着换框架,先看看是不是该给 useMemo 发工资了。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。