388 字
2 分钟
06 · 常用 Hooks
useMemo:缓存昂贵计算
const sorted = useMemo(() => bigList.sort(compare), [bigList]);只有 bigList 变才重新排序,否则复用上次结果。适合确实昂贵的计算——别什么都包,记忆本身有成本。
useCallback:缓存函数引用
const handle = useCallback(() => doSomething(a), [a]);返回稳定的函数引用,传给被 React.memo 包裹的子组件时,能避免因父组件重渲染生成新函数而导致子组件无谓重渲染。
useMemo/useCallback都要配合依赖数组;它们不是性能银弹,滥用反而慢。
useRef:可变盒子
const inputRef = useRef(null);// 访问 DOM<input ref={inputRef} />;inputRef.current.focus();
// 或存跨渲染的可变值(不触发重渲染)const timer = useRef();与 state 区别:ref.current 改了不会触发重渲染,适合存 DOM 引用、定时器 ID、上一次的值。
useContext:跨层传值
避免 props 层层透传(prop drilling):
const ThemeContext = createContext("light");function App() { return <ThemeContext.Provider value="dark"><Toolbar /></ThemeContext.Provider>;}function Toolbar() { const theme = useContext(ThemeContext); // 直接拿到,不用一层层传}注意:context 值变化会让所有消费组件重渲染,拆分 context 或结合 memo 控制范围。
小结
useMemo缓存计算、useCallback缓存函数,都按依赖、别滥用。useRef存可变值/ DOM 引用,改动不触发渲染。useContext解决 prop drilling,但变化会广播给所有消费者。
练习
- 一个列表组件,用
useMemo缓存”根据关键词过滤+排序”的结果。 - 用
useRef实现”组件挂载后自动聚焦输入框”。 - 写一个
ThemeContext,在深层子组件里读取主题值,体会免透传。