You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何React.memo无法缓存组件?父组件仍重渲染的原因探究

React.memo缓存失效:Parent组件意外重渲染的原因

问题场景

我遇到了React.memo缓存失效的问题,具体代码如下:

子组件与父组件定义

function Child() {
  useEffect(() => {
    console.log("Child rerender");
  });
  return <div>Child component</div>;
}

function Parent({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    console.log("Parent rerender");
  });
  return (
    <div>
      Parent component
      {children}
    </div>
  );
}

组件缓存处理

const ChildMemo = React.memo(Child);
const ParentMemo = React.memo(Parent);

顶层App组件

function App() {
  useEffect(() => {
    console.log("App rerender");
  });
  const [count, setCount] = useState(0);

  return (
    <>
      <button onClick={() => setCount(count + 1)}>Update state {count}</button>
      <ParentMemo>
        <ChildMemo />
      </ParentMemo>
    </>
  );
};

点击按钮触发App状态更新后,预期仅打印App rerender,但实际Parent组件也发生了重渲染。


原因分析

核心问题出在**children属性的引用变化**:

  • React.memo默认使用浅比较判断是否需要重渲染,只有当props的引用完全不变时,才会复用缓存的组件实例。
  • <ChildMemo />是React.createElement(ChildMemo, null)的语法糖,每次App组件重渲染时,都会重新执行这个方法生成全新的React元素对象,也就是传递给ParentMemo的children属性每次都是新的引用。
  • 浅比较发现children引用变化,因此ParentMemo会触发重渲染。

解决方案

要让ParentMemo的缓存生效,需保证传递给它的children引用稳定,有两种常用方式:

  1. 将子组件实例提到App组件外部
// 放在App组件外面,只会创建一次
const MemoizedChildInstance = <ChildMemo />;

function App() {
  useEffect(() => {
    console.log("App rerender");
  });
  const [count, setCount] = useState(0);

  return (
    <>
      <button onClick={() => setCount(count + 1)}>Update state {count}</button>
      <ParentMemo>
        {MemoizedChildInstance}
      </ParentMemo>
    </>
  );
};
  1. 使用useMemo缓存子组件实例
    如果子组件依赖App的状态无法放到外部,可用useMemo缓存:
function App() {
  useEffect(() => {
    console.log("App rerender");
  });
  const [count, setCount] = useState(0);
  
  // 空依赖数组保证仅在组件挂载时创建一次
  const memoizedChild = useMemo(() => <ChildMemo />, []);

  return (
    <>
      <button onClick={() => setCount(count + 1)}>Update state {count}</button>
      <ParentMemo>
        {memoizedChild}
      </ParentMemo>
    </>
  );
};

内容的提问来源于stack exchange,提问作者tnsaturday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:53:09