useMemo 与 useCallback
memo 挡不住“props 引用每次都变”的问题,需要 useMemo(缓存计算结果)与 useCallback(缓存函数本身)来稳定引用。二者依赖空数组时计算/创建只发生一次,之后渲染复用同一引用。
适用边界:不滥用——缓存本身有成本。给“计算昂贵的结果”“传给 memo 子组件的函数/对象 props”用即可;普通变量与内部回调不需要。频繁场景如大列表过滤、图表数据加工是典型受益点。
- useMemo(() => 结果, 依赖):缓存昂贵计算,依赖不变就复用
- useCallback(fn, 依赖):缓存函数引用,专供 memo 子组件 props 使用
- 两把锁要配对:memo 子组件 + 稳定 props,缺一不可
<!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>




