React Router 实战:嵌套路由、动态参数与导航守卫

test12026-09-273 次阅读

为什么需要路由层

单页应用里所有视图其实都来自同一个 HTML 入口,真正区分页面的是 URL。React Router 把 URL 映射到组件树,让浏览器前进、后退、刷新都能精确还原当前界面,同时支持数据预取与权限拦截。下面用 react-router-dom v6 的 data router 写法演示常见工程结构。

定义嵌套路由

嵌套路由的核心是一个路由同时渲染自身布局和它的子路由出口 Outlet,父级负责外壳,子级负责内容区。

import { createBrowserRouter, Outlet } from "react-router-dom";

function DashboardLayout() {
  return (
    <div>
      <aside>侧边栏</aside>
      <main><Outlet /></main>
    </div>
  );
}

export const router = createBrowserRouter([
  {
    path: "/dashboard",
    element: <DashboardLayout />,
    children: [
      { index: true, element: <Overview /> },
      { path: "reports", element: <Reports /> },
      { path: "settings", element: <Settings /> },
    ],
  },
]);

读取动态参数

列表页跳转到详情页时,ID 通常放在路径里。useParams 把路径片段解析成对象,配合类型断言即可得到强类型参数。

import { useParams } from "react-router-dom";

function ReportDetail() {
  const { id } = useParams<{ id: string }>();
  const [data, setData] = useState<Report | null>(null);

  useEffect(() => {
    fetch(`/api/reports/${id}`)
      .then((r) => r.json())
      .then(setData);
  }, [id]);

  if (!data) return <p>加载中</p>;
  return <h3>{data.title}</h3>;
}

导航守卫与鉴权拦截

受保护页面不应等到组件渲染才跳转,最佳做法是在 loader 阶段就判断登录态,未登录直接重定向到登录页,避免敏感数据请求泄露。

import { redirect, useNavigate } from "react-router-dom";

async function requireAuth({ request }: { request: Request }) {
  const token = localStorage.getItem("token");
  if (!token) {
    const url = new URL(request.url);
    return redirect(`/login?from=${url.pathname}`);
  }
  return null;
}

// 在路由配置里挂上 loader
{ path: "settings", element: <Settings />, loader: requireAuth };

组件内做临时跳转时,用 useNavigate 返回命令式导航,例如提交表单成功后跳回列表。

function CreateForm() {
  const navigate = useNavigate();
  const onSubmit = async (values: FormValues) => {
    await api.create(values);
    navigate("/dashboard/reports");
  };
  return <form onSubmit={handleSubmit(onSubmit)} />;
}

编程式导航与滚动恢复

data router 默认开启滚动恢复,刷新或后退都会回到原位置。如果需要在代码里精确控制,可结合 useLocation 做条件滚动。

import { useLocation } from "react-router-dom";

function ScrollToTop() {
  const { pathname } = useLocation();
  useEffect(() => {
    window.scrollTo(0, 0);
  }, [pathname]);
  return null;
}
  • 嵌套路由用 Outlet 把布局和内容解耦,避免每个页面重复写外壳。
  • 动态参数走 useParams,刷新后依然能从 URL 还原,对分享链接友好。
  • 鉴权守卫放在 loader 比放在组件里更早、更安全。
T

test1

文章作者

为什么需要路由层 单页应用里所有视图其实都来自同一个 HTML 入口,真正区分页面的是 URL。React Route...

分类
技术
发布时间
2026-09-27
字数
约 2379 字
阅读
3 次