React项目中react-router-dom v6下Admin与Public主题无法分离问题
问题原因
你的代码里,App.js同时渲染了PublicTheme和AdminTheme两个组件,不管当前访问的是哪个路径,这两个主题的头部和尾部都会一直存在于DOM中。路由切换时只是切换内部的页面组件,并不会控制主题组件的显示/隐藏,所以访问/admin/login时,公共主题的头尾也会显示。
解决方法
需要用react-router-dom v6的嵌套路由功能,让对应路径的路由匹配对应的主题组件,只有匹配到该路由组时,对应的主题才会被渲染。
步骤1:修改主题组件,使用Outlet替换children
react-router-dom的Outlet组件用于承载嵌套路由的子组件内容,替换原来的children属性:
修改AdminTheme
import { Outlet } from 'react-router-dom'; import Header from "../compenents/layout/Admin/Header"; import Footer from "../compenents/layout/Admin/Footer"; const AdminTheme = () => { return ( <> <Header /> <Outlet /> {/* 子路由的页面组件会渲染在这里 */} <Footer /> </> ); }; export default AdminTheme;
修改PublicTheme
import { Outlet } from 'react-router-dom'; import Header from "../compenents/layout/Public/Header"; import Footer from "../compenents/layout/Public/Footer"; const PublicTheme = () => { return ( <> <Header /> <main className="container mx-auto px-2 sm:px-4 pt-12"> <div className="flex flex-col lg:flex-row justify-between gap-x-8 mb-20"> <Outlet /> {/* 公共页面组件会渲染在这里 */} </div> </main> <Footer /> </> ); }; export default PublicTheme;
步骤2:重构App.js的路由结构
删除原来的AdminRoute和PublicRoute组件,直接在App.js中组织嵌套路由:
import { Routes, Route } from 'react-router-dom'; import PublicTheme from './compenents/layout/Public/PublicTheme'; import AdminTheme from './compenents/layout/Admin/AdminTheme'; // 导入页面组件 import Home from './compenents/pages/Home'; import Project from './compenents/pages/Project'; import Blog from './compenents/pages/Blog'; import Post from './compenents/pages/Post'; import Page404 from './compenents/pages/Page404'; import Login from './compenents/pages/Admin/Login'; import AdminPost from './compenents/pages/Admin/Post'; // 注意区分后台和公共的Post组件,避免命名冲突 function App() { return ( <Routes> {/* 公共路由组:匹配所有非/admin开头的路径,使用公共主题 */} <Route element={<PublicTheme />}> <Route path="/" element={<Home />} /> <Route path="/projects" element={<Project />} /> <Route path="/blog" element={<Blog />} /> <Route path="/posts" element={<Post />} /> <Route path="*" element={<Page404 />} /> </Route> {/* 后台路由组:匹配/admin开头的路径,使用后台主题 */} <Route element={<AdminTheme />}> <Route path="/admin/login" element={<Login />} /> <Route path="/admin/posts" element={<AdminPost />} /> </Route> </Routes> ); } export default App;
原理说明
- 嵌套路由会根据当前URL路径,匹配对应的父路由(主题组件),只有匹配成功的父路由才会被渲染,从而保证同一时间只有一个主题的头尾存在。
Outlet组件相当于父路由的“占位符”,子路由的页面组件会被渲染到Outlet的位置,实现主题框架和页面内容的分离。
内容的提问来源于stack exchange,提问作者JFeel
相关产品推荐
相关产品推荐

