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

React使用条件渲染与children prop时如何避免子组件重渲染

悬停父组件触发子组件重渲染问题修复

问题场景

有一个复用了大部分通用逻辑的组件,需要解决鼠标悬停父组件时子组件意外重渲染的问题,初始实现代码如下:

const ReusableComponent = ({ conditional }) => {
  const [isHovered, setIsHovered] = useState(false);

  const AnotherReusableComponent = ({ children }) => (
    <div>{children}</div>
  );

  const renderComponent = () => {
    if (conditional) {
      return <ComponentA />;
    };

    return <ComponentB />;
  };

  return (
    <div>
      <title 
        onMouseEnter={() => setIsHovered(true)}
        onMouseLeave={() => setIsHovered(false)}
      >
        Menu
      </title>
      <div className={isHovered ? 'oneClass' : 'otherClass'}>
        <AnotherReusableComponent>
          {renderComponent()}
        </AnotherReusableComponent>
      </div>
    </div>
  );
}

已知信息

  • ComponentA和ComponentB根据外层className值控制显示与隐藏
  • 悬停事件用于切换className的取值
  • 已尝试使用memo进行优化,但没有生效
  • 重渲染行为仅在触发悬停事件时发生

根本原因

memo失效的核心原因是在ReusableComponent的渲染函数内部定义了AnotherReusableComponent组件和renderComponent方法:

  • 每次isHovered变化触发父组件重渲染时,这两个声明都会重新执行,生成完全新的引用
  • React判定组件类型变化时,会直接卸载旧组件、重新挂载新组件,memo的浅比较逻辑根本不会触发,自然无法生效

修复方案

  1. 将渲染函数内部定义的子组件移到组件外部,保证组件引用稳定
  2. 移除不必要的内部渲染函数,直接在JSX中写条件渲染逻辑,避免函数引用变化带来的重渲染
  3. 给需要缓存的子组件包裹memo,此时props不变时就不会触发重渲染

修复后的代码:

import { useState, memo, useCallback } from 'react';

// 移到父组件外部,保证引用稳定
const AnotherReusableComponent = ({ children }) => (
  <div>{children}</div>
);

// 子组件包裹memo实现渲染缓存
const MemoComponentA = memo(ComponentA);
const MemoComponentB = memo(ComponentB);

const ReusableComponent = ({ conditional }) => {
  const [isHovered, setIsHovered] = useState(false);

  // 事件函数用useCallback缓存,避免每次渲染生成新引用
  const handleMouseEnter = useCallback(() => setIsHovered(true), []);
  const handleMouseLeave = useCallback(() => setIsHovered(false), []);

  return (
    <div>
      <title 
        onMouseEnter={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
      >
        Menu
      </title>
      <div className={isHovered ? 'oneClass' : 'otherClass'}>
        <AnotherReusableComponent>
          {conditional ? <MemoComponentA /> : <MemoComponentB />}
        </AnotherReusableComponent>
      </div>
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:12:25