React Router 中的 useOutlet 是 v6
版本新增的 Hook,用于在父路由组件中访问当前嵌套的子路由元素。它提供了比 <Outlet>
组件更灵活的控制方式,适合需要根据子路由状态进行动态处理的场景。
一、useOutlet的基本用法
import { useOutlet } from 'react-router-dom';
function ParentLayout() {
// 返回当前匹配的子路由元素(未匹配时返回 null)
const outlet = useOutlet();
return (
<div>
<h1>Parent Layout</h1>
<nav>{/* 导航链接 */}</nav>
{/* 等价于直接使用 <Outlet /> */}
{outlet || <div>Default content when no sub-route matches</div>}
</div>
);
}
二、useOutlet的典型使用场景
2.1. 条件渲染布局
function AuthLayout() {
const outlet = useOutlet();
return (
<div className="auth-layout">
{outlet ? (
// 有子路由时显示带背景的布局
<div className="auth-background">
{outlet}
</div>
) : (
// 无子路由时显示默认内容
<Navigate to="/login" />
)}
</div>
);
}
2.2. 动态处理子路由
function AnimationLayout() {
const outlet = useOutlet();
const [prevOutlet, setPrevOutlet] = useState(outlet);
// 保留旧路由用于退场动画
if (outlet) setPrevOutlet(outlet);
return (
<AnimatePresence mode="wait">
<motion.div
key={location.pathname}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
{outlet || prevOutlet}
</motion.div>
</AnimatePresence>
);
}
三、useOutlet的路由配置示例
const router = createBrowserRouter([
{
path: '/',
element: <ParentLayout />,
children: [
{
path: 'dashboard',
element: <Dashboard />,
},
{
path: 'profile',
element: <UserProfile />,
}
]
}
]);
四、useOutlet的使用注意事项
4.1、上下文依赖
只能在被 <RouterProvider>
或 <BrowserRouter>
包裹的组件中使用,否则会抛出错误。
4.2、路由匹配规则
子路由需要正确配置在父路由的 children 数组中,且路径需要正确嵌套:
// ❌ 错误配置(缺少父路径)
children: [{ path: '/dashboard', ... }]
// ✅ 正确配置
children: [{ path: 'dashboard', ... }] // 实际路径为 /dashboard
4.3、null 值处理
当没有匹配的子路由时返回 null,建议总是处理空状态:
// 推荐写法
{outlet || <FallbackComponent />}
// 危险写法(可能渲染 undefined)
{outlet}
4.4、性能优化
与 <Outlet>
不同,直接使用 useOutlet
不会自动处理 Suspense
,需要自行添加错误边界:
function SafeOutlet() {
const outlet = useOutlet();
return <ErrorBoundary>{outlet}</ErrorBoundary>;
}
4.5、路由状态更新
当 URL 变化但父路由保持匹配时,useOutlet
会返回新的 React 元素,可以用 useLocation
监听变化:
const outlet = useOutlet();
const location = useLocation();
useEffect(() => {
console.log('Sub-route changed:', location.pathname);
}, [location]);
五、useOutlet 与 的对比
六、useOutlet 使用总结建议:
大多数简单场景直接使用 <Outlet>
更合适
需要以下高级功能时选择 useOutlet:
6.1、动态布局切换
6.2、路由过渡动画
6.3、自定义空状态处理
6.4、基于子路由的复杂条件渲染