React 第三十七节 Router 中 useOutlet Hook的使用介绍以及注意事项

发布于:2025-05-09 ⋅ 阅读:(15) ⋅ 点赞:(0)

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、基于子路由的复杂条件渲染


网站公告

今日签到

点亮在社区的每一天
去签到