为了子组件不必要的重复渲染,React 使用 memo / useMemo / useCallback 进行缓存处理。

它们分别解决了两个问题:

  1. 防止 props 不变时的重复渲染

  2. 防止 props 自身不必要的变化

其中,memouseMemo / useCallback 需要同时使用,否则实际上起不到缓存的效果。

memo 的使用

memo 的出现,使得子组件只有在 props 变化时才会被重新渲染,也就解决了“props 不变时的重复渲染”的问题。

function Children({ count }) {
  return <div>{count}</div>;
}

// 缓存组件
const MemoChildren = memo(Children);

function Container() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <MemoChildren count={count} />
      <button onClick={() => setCount((count) => count + 1)}>+</button>
    </div>
  );
}

useMemo 和 useCallback

这两个 hooks 都是在对 state 进行缓存,不同的是一个存变量、一个存函数。它们在父组件里缓存要传递给子组件的变量,起到了“防止 props 自身不必要的变化”的作用。

function Children({ count, cb }) {
  return (
    <div>
      <span>{count}</span>
      <button onClick={() => cb(count + 1)}>+</button>
    </div>
  );
}

const MemoChildren = memo(Children);

function Container() {
  const [count, setCount] = useState(0);

  const value = useMemo(() => count + 3, [count]);

  const handleCb = useCallback(() => {
    setCount(count - 3);
  }, []);

  return <MemoChildren count={value} cb={handleCb} />;
}

注意:如果传递给 MemoChildren 的变量没有用 useMemouseCallback,父组件每次都会产生新的变量和函数,props 就会一直变化,即使有 memo 也无法起到缓存作用