React中如何让header、menu、footer仅在私有路由渲染且只渲染一次
解决方案
核心思路
通过两级路由拆分+带缓存的私有布局组件实现需求:将Header、Menu、Footer统一封装到不可重渲染的PrivateLayout布局组件中,所有私有路由作为该布局组件的子路由存在,非私有路由直接在根路由层级独立配置。
具体实现步骤
- 第一步:封装
PrivateLayout私有布局组件
组件内集成Header、Menu、Footer三个公共组件,类组件直接继承React.PureComponent或手动设置shouldComponentUpdate返回false,保证组件只要不卸载就不会触发重渲染;组件挂载时仅执行一次从localStorage拉取登录数据的逻辑,初始化三个公共组件的状态。 - 第二步:配置两级路由结构
根路由下拆分两类路由:非私有路由(登录页、注册页等不需要公共布局的页面)直接指向对应页面组件;所有私有路由统一归到PrivateLayout作为父路由的子路由下。
以下为React Router v6的配置示例:import { Routes, Route } from 'react-router-dom' import PrivateLayout from './PrivateLayout' import Login from './pages/Login' import Home from './pages/Home' import UserCenter from './pages/UserCenter' function App() { return ( <Routes> {/* 非私有路由,无公共布局 */} <Route path="/login" element={<Login />} /> {/* 私有路由组,统一挂载公共布局 */} <Route path="/" element={<PrivateLayout />}> <Route index element={<Home />} /> <Route path="user" element={<UserCenter />} /> {/* 其余私有路由均在此处添加 */} </Route> </Routes> ) }PrivateLayout组件示例代码:
如果使用React Router v5,只需将私有路由的配置调整为嵌套渲染import React from 'react' import { Navigate, Outlet } from 'react-router-dom' import Header from './Header' import Menu from './Menu' import Footer from './Footer' // 继承PureComponent保证state/props无变化时不触发重渲染 class PrivateLayout extends React.PureComponent { state = { userInfo: null, isLogin: false } componentDidMount() { // 仅挂载时执行一次数据拉取 const userInfo = localStorage.getItem('userInfo') if (userInfo) { this.setState({ userInfo: JSON.parse(userInfo), isLogin: true }) } } render() { // 未登录直接跳转登录页,避免公共布局暴露 if (!this.state.isLogin) return <Navigate to="/login" replace /> return ( <div className="private-layout"> <Header userInfo={this.state.userInfo} /> <Menu userInfo={this.state.userInfo} /> {/* 子路由出口,切换私有路由仅此处更新 */} <Outlet /> <Footer /> </div> ) } } export default PrivateLayoutPrivateLayout的模式即可,核心逻辑不变。
效果验证
- 访问非私有路由时
PrivateLayout不会被加载,三个公共组件不会渲染 - 进入任意私有路由后
PrivateLayout首次挂载,三个公共组件仅渲染一次,后续切换不同私有路由时仅子路由对应页面更新,公共布局不会触发重渲染
内容的提问来源于stack exchange,提问作者Leo Bruno
相关产品推荐
相关产品推荐

