FORMA

Memo、Callback 与 Ref

本文介绍 useRefuseMemouseCallbackmemo 及自定义 Hook。见 Effect

useRef

保存跨渲染可变值,修改 .current 不触发重新渲染。

tsx
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)
tsx
const sorted = useMemo(() => [...items].sort(compare), [items]);
const handleClick = useCallback(() => {
  onSelect(id);
}, [id, onSelect]);

原则:先保证正确性,仅在性能分析后、且子组件因引用变化导致多余渲染时再使用。过度使用增加复杂度。

React.memo

对组件进行浅比较 props,props 未变则跳过重新渲染:

tsx
const Row = memo(function Row({ item }: { item: Item }) {
  return <li>{item.name}</li>;
});

需配合稳定的 props(如 useCallback 传递的函数)才有效。

自定义 Hook

use 开头的函数,内部可调用其他 Hooks,用于复用逻辑:

tsx
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 思路类似。

参考文献

以下链接在编写时均可正常访问:

Series

hooks

3 / 4