React-Router

Ⅰ.基础路由配置

import { createBrowserRouter, RouterProvider } from 'react-router-dom';

// 1. 定义路由配置
const router = createBrowserRouter([
  {
    path: '/',
    element: <HomePage />,
  },
  {
    path: '/about',
    element: <AboutPage />,
  },
]);

// 2. 挂载路由
ReactDOM.createRoot(root).render(
  <RouterProvider router={router} />
);

Ⅱ.嵌套路由

1.基础嵌套结构

通过<Outlet>实现布局嵌套

const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />, // 父级布局
    children: [
      {
        index: true, // 默认路由
        element: <Dashboard />,
      },
      {
        path: 'profile',
        element: <Profile />,
      },
      {
        path: 'settings',
        element: <Settings />,
      },
    ],
  },
]);

// Layout 组件使用 Outlet
function Layout() {
  return (
    <div>
      <header>导航栏</header>
      <main>
        <Outlet /> {/* 子路由渲染位置 */}
      </main>
      <footer>页脚</footer>
    </div>
  );
}

2.多级嵌套

const router = createBrowserRouter([
  {
    path: '/admin',
    element: <AdminLayout />,
    children: [
      {
        path: 'users',
        element: <UserManagementLayout />,
        children: [
          {
            path: 'list',
            element: <UserList />,
          },
          {
            path: 'create',
            element: <UserCreate />,
          },
        ],
      },
    ],
  },
]);

Ⅲ.动态路由

1.定义动态参数

const router = createBrowserRouter([
  {
    path: '/users/:userId',
    element: <UserDetail />,
  },
  {
    path: '/products/:category/:id',
    element: <ProductDetail />,
  },
]);

// 组件中获取参数
import { useParams } from 'react-router-dom';

function UserDetail() {
  const { userId } = useParams(); // { userId: "123" }
  return <div>用户ID: {userId}</div>;
}

function ProductDetail() {
  const { category, id } = useParams(); // { category: "electronics", id: "456" }
  return <div>分类: {category}, ID: {id}</div>;
}

2.可选参数和通配符

const router = createBrowserRouter([
  {
    path: '/docs/:section?', // 可选参数
    element: <Documentation />,
  },
  {
    path: '/files/*', // 通配符匹配所有子路径
    element: <FileBrowser />,
  },
]);

Ⅳ.编程式导航

1.使用useNavigate

import { useNavigate } from 'react-router-dom';

function NavigationExample() {
  const navigate = useNavigate();
  
  const handleNavigation = () => {
    // 基础导航
    navigate('/target-path');
    
    // 带状态导航
    navigate('/dashboard', {
      state: { from: 'login' },
      replace: true, // 替换历史记录
    });
    
    // 相对路径导航
    navigate('../parent'); // 上一级
    navigate('./child');    // 当前路径下的子路径
  };
  
  return (
    <div>
      <button onClick={() => navigate(-1)}>返回</button>
      <button onClick={() => navigate(1)}>前进</button>
      <button onClick={handleNavigation}>跳转</button>
    </div>
  );
}

2.重定向组件

import { Navigate } from 'react-router-dom';

function ProtectedRoute({ isAuthenticated, children }) {
  return isAuthenticated ? children : <Navigate to="/login" replace />;
}

// 使用示例
<Route 
  path="/admin" 
  element={
    <ProtectedRoute isAuthenticated={user.isAdmin}>
      <AdminPanel />
    </ProtectedRoute>
  } 
/>

Ⅴ.路由守卫

1.高阶组件形式

import { Navigate, useLocation } from 'react-router-dom';

function RequireAuth({ children, roles = [] }) {
  const auth = useAuth();
  const location = useLocation();
  
  if (!auth.user) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }
  
  if (roles.length > 0 && !roles.includes(auth.user.role)) {
    return <Navigate to="/unauthorized" replace />;
  }
  
  return children;
}

// 使用示例
const router = createBrowserRouter([
  {
    path: '/admin',
    element: (
      <RequireAuth roles={['admin', 'superadmin']}>
        <AdminPanel />
      </RequireAuth>
    ),
  },
]);

2.Loader拦截

// 权限校验 Loader
export async function adminLoader({ request }) {
  const user = await getCurrentUser();
  
  if (!user) {
    throw redirect('/login');
  }
  
  if (user.role !== 'admin') {
    throw redirect('/unauthorized');
  }
  
  return { user };
}

// 路由配置
const router = createBrowserRouter([
  {
    path: '/admin',
    element: <AdminPanel />,
    loader: adminLoader, // 路由级别权限控制
  },
]);

Ⅵ.特殊路由配置

1.404页面

const router = createBrowserRouter([
  // ...其他路由
  {
    path: '*',
    element: <NotFoundPage />,
  },
]);

Ⅶ.数据加载

1.Loader数据预加载

import { json } from 'react-router-dom';

// 用户详情页 Loader
export async function userLoader({ params, request }) {
  const userId = params.userId;
  
  try {
    const user = await fetchUser(userId);
    const posts = await fetchUserPosts(userId);
    
    return json({ user, posts });
  } catch (error) {
    throw new Response('用户不存在', { status: 404 });
  }
}

// 组件中使用数据
import { useLoaderData } from 'react-router-dom';

function UserProfile() {
  const { user, posts } = useLoaderData();
  
  return (
    <div>
      <h1>{user.name}</h1>
      {posts.map(post => (
        <article key={post.id}>{post.title}</article>
      ))}
    </div>
  );
}

2.Action数据处理

// 表单提交 Action
export async function userAction({ request, params }) {
  const formData = await request.formData();
  const intent = formData.get('intent');
  
  switch (intent) {
    case 'update':
      return updateUser(params.userId, formData);
    case 'delete':
      return deleteUser(params.userId);
    default:
      throw new Error('未知操作');
  }
}

// 表单组件
function UserForm() {
  return (
    <Form method="post">
      <input type="text" name="name" />
      <button type="submit" name="intent" value="update">
        更新
      </button>
      <button type="submit" name="intent" value="delete">
        删除
      </button>
    </Form>
  );
}

Ⅷ.高级特性

1.懒加载路由

const router = createBrowserRouter([
  {
    path: '/dashboard',
    lazy: () => import('./routes/Dashboard'), // 动态导入
  },
  {
    path: '/admin',
    lazy: async () => {
      const { AdminLayout, adminLoader } = await import('./routes/Admin');
      return { 
        Component: AdminLayout, 
        loader: adminLoader 
      };
    },
  },
]);

2.错误边界处理

// 路由级别错误处理
const router = createBrowserRouter([
  {
    path: '/',
    element: <Root />,
    errorElement: <ErrorBoundary />, // 错误边界组件
    children: [
      {
        path: 'users/:userId',
        element: <UserDetail />,
        errorElement: <UserError />, // 子路由错误处理
      },
    ],
  },
]);

// 错误边界组件
function ErrorBoundary() {
  const error = useRouteError();
  
  return (
    <div>
      <h1>出错了!</h1>
      <p>{error.statusText || error.message}</p>
    </div>
  );
}

3.滚动恢复

import { ScrollRestoration } from 'react-router-dom';

function Root() {
  return (
    <>
      <ScrollRestoration /> {/* 自动恢复滚动位置 */}
      <Outlet />
    </>
  );
}

Ⅸ.最佳实践

1.项目组织结构

src/
├── routes/ # 路由组件
│ ├── index.tsx # 首页
│ ├── about/
│ │ ├── index.tsx
│ │ └── team.tsx
│ └── users/
│ ├── index.tsx
│ ├── [id].tsx # 动态路由
│ └── create.tsx
├── components/ # 共享组件
├── layouts/ # 布局组件
├── router/ # 路由配置
│ └── index.ts
└── main.tsx

2.类型安全配置

// router/types.ts
import { RouteObject } from 'react-router-dom';

export interface AppRoute extends RouteObject {
  meta?: {
    title?: string;
    requiresAuth?: boolean;
    roles?: string[];
  };
  children?: AppRoute[];
}

// router/config.ts
export const routes: AppRoute[] = [
  {
    path: '/',
    element: <Home />,
    meta: { title: '首页' },
  },
];

3.性能优化技巧

// 1. 代码分割
const LazyComponent = lazy(() => import('./HeavyComponent'));

// 2. 预加载
<Link to="/dashboard" onMouseEnter={() => preloadDashboard()} />

// 3. 记忆化导航
const navigate = useNavigate();
const memoizedNavigate = useCallback((path: string) => {
  navigate(path);
}, [navigate]);

Life's a struggle, I'll conquer it.
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇