React Router双Outlet实现及NavLink isActive未定义问题求助
关于多Outlet/条件渲染的实现方案
你不需要必须用嵌套路由来实现,React Router v6+支持命名Outlet,可以直接在布局里放置多个带名字的Outlet,也可以通过路由判断做条件渲染,两种方案都可行:
方案1:使用命名Outlet
修改你的Layout组件,添加命名Outlet:
import React from 'react'; import Header from './components/Header/Header'; import Footer from './components/Footer/Footer'; import { Outlet } from 'react-router-dom'; function Layout() { return ( <> <Header /> {/* 默认Outlet */} <Outlet /> {/* 命名Outlet,比如叫secondary */} <Outlet name="secondary" /> <Footer /> </> ); } export default Layout;
然后在路由配置中,指定组件渲染到对应Outlet:
import { createBrowserRouter, RouterProvider } from 'react-router-dom'; import Layout from './Layout'; import MainContent from './MainContent'; import SpecialContent1 from './SpecialContent1'; import SpecialContent2 from './SpecialContent2'; const router = createBrowserRouter([ { path: '/', element: <Layout />, children: [ // 默认渲染到无命名的Outlet { path: '/', element: <MainContent /> }, // 特定路由下,同时渲染到默认和secondary Outlet { path: '/special', children: [ { index: true, element: <SpecialContent1 /> }, { path: '/special', element: <SpecialContent2 />, outlet: 'secondary' }, ], }, ], }, ]); function App() { return <RouterProvider router={router} />; }
方案2:条件渲染组件
如果只是针对特定路由切换组件,也可以直接在Layout中通过useLocation获取当前路由做判断:
import React from 'react'; import Header from './components/Header/Header'; import Footer from './components/Footer/Footer'; import { Outlet, useLocation } from 'react-router-dom'; import SpecialComponent from './SpecialComponent'; import NormalComponent from './NormalComponent'; function Layout() { const location = useLocation(); const isSpecialRoute = location.pathname === '/special'; return ( <> <Header /> {/* 条件渲染不同组件 */} {isSpecialRoute ? <SpecialComponent /> : <Outlet />} {/* 第二个条件渲染的组件 */} {isSpecialRoute ? <AnotherSpecialComponent /> : <DefaultSecondaryComponent />} <Footer /> </> ); } export default Layout;
你报错的核心原因是:className回调里的isActive是局部变量,无法在NavLink的子JSX中直接访问。要在子元素中获取激活状态,需要把NavLink的children作为函数使用,这样就能拿到包含isActive的状态对象。
修改后的代码如下:
<NavLink to="/" onClick={handleHomeClick} className={({ isActive }) => `block py-2 pr-4 pl-3 duration-200 ${isActive ? "text-orange-700" : "text-gray-700"} border-b border-gray-100 hover:bg-gray-50 lg:hover:bg-transparent lg:border-0 hover:text-orange-700 lg:p-0` } aria-current="page" > {/* 把children改成函数,接收状态对象 */} {({ isActive }) => ( <> HOME {isActive && ( <div className="absolute top-full left-1/2 transform -translate-x-1/2 w-2 h-2 mt-1 border-2 border-yellow-500 bg-black rotate-45" /> )} </> )} </NavLink>
这样就能正确拿到isActive状态,不会再报未定义的错误。
内容的提问来源于stack exchange,提问作者Ainz
相关产品推荐
相关产品推荐

