useMemo(缓存计算结果)与 useMemo(缓存计算结果)与 useMemo(缓存计算结果)与
React 词条目录
前端Wiki/React/深入/性能优化与自定义 Hook

useMemo 与 useCallback

memo 挡不住“props 引用每次都变”的问题,需要 useMemo(缓存计算结果)与 useCallback(缓存函数本身)来稳定引用。二者依赖空数组时计算/创建只发生一次,之后渲染复用同一引用。

适用边界:不滥用——缓存本身有成本。给“计算昂贵的结果”“传给 memo 子组件的函数/对象 props”用即可;普通变量与内部回调不需要。频繁场景如大列表过滤、图表数据加工是典型受益点。

  • useMemo(() => 结果, 依赖):缓存昂贵计算,依赖不变就复用
  • useCallback(fn, 依赖):缓存函数引用,专供 memo 子组件 props 使用
  • 两把锁要配对:memo 子组件 + 稳定 props,缺一不可
HTML
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>useMemo / useCallback</title>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState, useMemo, useCallback, memo } = React;

const Heavy = memo(function Heavy({ data, onClick }) {
  console.log('Heavy 渲染');   // count 变化时它不再渲染
  return <li onClick={onClick}>{data}(点击+1)</li>;
});

function App() {
  const [count, setCount] = useState(0);
  const [kw, setKw] = useState('');

  // 昂贵计算:只有 kw 变才算一次
  const result = useMemo(() => {
    console.log('重新计算');
    return kw.split('').reverse().join('') || '(空)';
  }, [kw]);

  // 稳定函数引用:传给 memo 子组件不会失效
  const addItem = useCallback(() => setCount(c => c + 1), []);

  return (
    <div style={{ padding: 16 }}>
      <p>count = {count}</p>
      <input placeholder="输入触发计算" value={kw} onChange={e => setKw(e.target.value)} />
      <p>反转结果:{result}</p>
      <ul><Heavy data="第 1 项" onClick={addItem} /></ul>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
本节要点useMemo 缓存昂贵计算、useCallback 稳定函数引用,配合 memo 子组件才生效。
🔗 相关词条JavaScript面试题库Vue