Memo、Callback 与 Ref
本文介绍 useRef、useMemo、useCallback、memo 及自定义 Hook。见 Effect。
useRef
保存跨渲染可变值,修改 .current 不触发重新渲染。
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
return <input ref={inputRef} />;
也用于保存定时器 id、上一次的 props、避免闭包陈旧等。
useMemo / useCallback
| Hook | 作用 |
|---|---|
useMemo(() => compute(a, b), [a, b]) | 缓存计算结果 |
useCallback(fn, deps) | 缓存函数引用(等价于 useMemo(() => fn, deps)) |
const sorted = useMemo(() => [...items].sort(compare), [items]);
const handleClick = useCallback(() => {
onSelect(id);
}, [id, onSelect]);
原则:先保证正确性,仅在性能分析后、且子组件因引用变化导致多余渲染时再使用。过度使用增加复杂度。
React.memo
对组件进行浅比较 props,props 未变则跳过重新渲染:
const Row = memo(function Row({ item }: { item: Item }) {
return <li>{item.name}</li>;
});
需配合稳定的 props(如 useCallback 传递的函数)才有效。
自定义 Hook
以 use 开头的函数,内部可调用其他 Hooks,用于复用逻辑:
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const onResize = () => setWidth(window.innerWidth);
window.addEventListener("resize", onResize);
return () => window.removeEventListener("resize", onResize);
}, []);
return width;
}
一个自定义 Hook 对应一个逻辑关注点,与 Vue Composables 思路类似。
参考文献
以下链接在编写时均可正常访问:
| 资料 | 说明 |
|---|---|
| React:useRef | API |
| React:useMemo | API |
| React:useCallback | API |
| React:memo | API |
| React:自定义 Hook | 复用逻辑 |
相关文章
Effect 与副作用
useEffect 用于在组件渲染后执行与外部系统同步的逻辑(请求、订阅、手动改 DOM 等)。涵盖基本用法、依赖数组、适用/不适用场景、useLayoutEffect、最佳实践与常见坑。
Context
Context 在组件树中跨层级传递数据,避免 props 逐层透传。涵盖创建与使用、自定义 Hook 封装、性能拆分、与全局状态库对照、最佳实践与常见坑。
State 与 Reducer
Hooks 让函数组件拥有 state 与副作用能力。本文介绍 useState 与 useReducer。见 React 基础。
渲染与协调
React 将组件渲染为虚拟 DOM 树,再协调(reconciliation)到浏览器 DOM。理解该过程有助于解释 key、memo 与性能优化。涵盖渲染流程、Fiber、startTransition、Suspense、最佳实践与常见坑。
工程化
新建 React 项目时,官方与社区主流工具为 Vite;全栈场景常用 Next.js。涵盖 Vite + React、Create React App 现状、Next.js、目录结构、环境变量、部署、最佳实践与常见坑。
TypeScript
React 官方推荐 TypeScript。类型主要落在 Props、事件、Ref 与 Hooks 返回值上。见 组件。
Series
hooks
3 / 4