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

React:如何在静态NavBar组件内渲染子组件且避免重渲染?

解决React NavBar组件渲染子组件且避免重渲染的问题

要实现在NavBar内渲染子组件同时避免其不必要重渲染,核心思路是让NavBar只在自身props真正变化时才重新渲染,同时确保传递给它的props(包括children)引用稳定。以下是具体步骤和代码示例:

1. 让NavBar组件具备“按需渲染”能力

首先要确保NavBar不会因为父组件的无关渲染而跟着刷新,我们可以通过React的内置优化工具实现:

如果是函数组件:用React.memo包裹

React.memo会对组件的props进行浅比较,只有当props真正变化时才重新渲染组件:

import React, { memo } from 'react';
import { NavBar as AntNavBar } from 'antd';

const NavBar = memo(({ title, children }) => {
  // 可以加个日志测试是否重渲染
  console.log('NavBar 渲染了');
  return (
    <AntNavBar title={title}>
      {children} {/* 这里渲染传入的子组件 */}
    </AntNavBar>
  );
});

export default NavBar;

如果是类组件:继承PureComponent

PureComponent会自动在shouldComponentUpdate中浅比较props和state,避免不必要的重渲染:

import React, { PureComponent } from 'react';
import { NavBar as AntNavBar } from 'antd';

class NavBar extends PureComponent {
  render() {
    console.log('NavBar 渲染了');
    const { title, children } = this.props;
    return (
      <AntNavBar title={title}>
        {children}
      </AntNavBar>
    );
  }
}

export default NavBar;

2. 稳定传递children的引用

父组件(比如你的App组件)在路由切换时会重新渲染,如果直接在render里创建NavBar的子组件,每次都会生成新的JSX引用,导致NavBar的children props变化,触发重渲染。我们需要让children的引用保持稳定:

方案一:静态子组件用useMemo缓存(函数组件App)

如果NavBar的子组件是静态的(比如导航菜单),用useMemo缓存它,确保每次父组件渲染时引用不变:

import { HashRouter, Route } from 'react-router-dom';
import React, { useMemo } from 'react';
import NavBar from './NavBar';
import HomePage from './HomePage';
import MarketPage from './MarketPage';
import { Menu } from 'antd';

function App() {
  console.log('App 渲染了');
  // 用useMemo缓存导航菜单,空依赖数组确保只创建一次
  const navChildren = useMemo(() => (
    <Menu mode="horizontal">
      <Menu.Item key="home">首页</Menu.Item>
      <Menu.Item key="market">市场</Menu.Item>
    </Menu>
  ), []);

  return (
    <HashRouter>
      <div className="App">
        {/* 静态导航区 */}
        <div>
          <NavBar title="MyApp">{navChildren}</NavBar>
        </div>
        {/* 动态路由区 */}
        <div>
          {/* 注意修正路由path:把"//"改成"/"并加上exact,避免匹配所有路由 */}
          <Route exact path="/" component={HomePage} />
          <Route path="/market" component={MarketPage}/>
        </div>
      </div>
    </HashRouter>
  );
}

export default App;

方案二:把静态子组件作为类实例属性(类组件App)

如果你的App是类组件,可以把NavBar的子组件放在类的实例属性中,避免每次render重新创建:

import { HashRouter, Route } from 'react-router-dom';
import React, { Component } from 'react';
import NavBar from './NavBar';
import HomePage from './HomePage';
import MarketPage from './MarketPage';
import { Menu } from 'antd';

class App extends Component {
  // 把导航菜单作为实例属性,只创建一次
  navChildren = (
    <Menu mode="horizontal">
      <Menu.Item key="home">首页</Menu.Item>
      <Menu.Item key="market">市场</Menu.Item>
    </Menu>
  );

  render() {
    console.log('App 渲染了');
    return (
      <HashRouter>
        <div className="App">
          <div>
            <NavBar title="MyApp">{this.navChildren}</NavBar>
          </div>
          <div>
            <Route exact path="/" component={HomePage} />
            <Route path="/market" component={MarketPage}/>
          </div>
        </div>
      </HashRouter>
    );
  }
}

export default App;

3. 验证效果

现在切换路由时,你会看到控制台只打印App 渲染了,而不会打印NavBar 渲染了,说明NavBar没有跟着重渲染,同时它的子组件也能正常显示。

关键总结

  • 组件优化:用React.memo(函数组件)或PureComponent(类组件)让NavBar只在props变化时渲染
  • 稳定props:确保传递给NavBar的所有props(包括children)引用不变,避免父组件渲染时触发不必要的props更新
  • 路由修正:原代码中的path="//"是错误的,改成path="/"并加上exact,避免路由匹配异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:25:33