Skip to content

React Router v6 路由重定向指南

问题描述

在 React Router v6 中,许多开发者遇到了路由重定向的问题。与 v5 版本不同,v6 中不再支持在 Route 组件中使用 render 属性来实现重定向功能。当尝试使用类似 v5 的语法时,会出现 TypeScript 错误:Property 'render' does not exist on type...

解决方案

1. 使用 Navigate 组件进行基本重定向

React Router v6 引入了 Navigate 组件来替代 v5 中的 Redirect 组件:

jsx
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';

<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/lab" element={<Lab />} />
    <Route path="*" element={<Navigate to="/" replace />} />
  </Routes>
</BrowserRouter>

提示

使用 replace 属性可以避免在浏览器历史记录中创建多余的条目,保持历史记录清洁。

2. 处理 404 路由

使用通配符路径 * 来捕获所有未匹配的路由:

jsx
<Route path="*" element={<Navigate to="/" replace />} />

或者显示自定义的 404 页面:

jsx
<Route path="*" element={<NotFound />} />

3. 条件重定向

根据应用状态进行条件重定向:

jsx
// 在组件内部使用
import { useState } from "react";
import { Navigate } from "react-router-dom";

function ProtectedComponent() {
  const [isLoggedIn] = useState(false);
  
  if (!isLoggedIn) {
    return <Navigate to="/login" replace />;
  }
  
  return <div>受保护的内容</div>;
}

4. 编程式导航

使用 useNavigate hook 进行编程式导航:

jsx
import { useNavigate } from "react-router-dom";

function MyComponent() {
  const navigate = useNavigate();
  
  const handleRedirect = () => {
    // 替换当前历史记录
    navigate("/target-path", { replace: true });
    
    // 或者添加新历史记录(默认行为)
    // navigate("/target-path");
  };
  
  return (
    <button onClick={handleRedirect}>
      跳转到目标页面
    </button>
  );
}

5. 认证保护路由

创建高阶组件来保护需要认证的路由:

jsx
import { useLocation, Navigate } from "react-router-dom";
import { useAuth } from "../hooks/Auth";

export function RequireAuth({ children }) {
  let { user } = useAuth();
  let location = useLocation();

  if (!user) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }
  
  return children;
}

使用保护路由:

jsx
<Route
  path="/dashboard"
  element={
    <RequireAuth>
      <Dashboard />
    </RequireAuth>
  }
/>

6. 保留参数的重定向

当需要重定向并保留 URL 参数时,可以使用自定义组件:

jsx
import { useEffect } from 'react';
import { generatePath, useNavigate, useParams } from 'react-router-dom';

function Redirect({ to }) {
  const navigate = useNavigate();
  const params = useParams();

  useEffect(() => {
    navigate(generatePath(to, params), { replace: true });
  }, [navigate, to, params]);

  return null;
}

// 使用方式
<Route path="/users/:id" element={<Redirect to="/new-path/:id" />} />

常见问题解答

注意

React Router v6 不再支持在 Route 组件中使用 rendercomponentchildren 属性,请使用 element 属性代替。

Q: 如何从类组件中进行重定向?

A: 对于类组件,可以使用高阶组件(HOC)来注入导航功能:

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

export const withRouter = WrappedComponent => props => {
  return <WrappedComponent {...props} navigate={useNavigate()} />;
};

// 在类组件中使用
class MyComponent extends React.Component {
  // ...
  handleRedirect = () => {
    this.props.navigate("/target-path");
  }
  // ...
}

export default withRouter(MyComponent);

Q: 重定向时如何传递状态?

A: 使用 state 属性传递状态数据:

jsx
navigate("/target-path", { 
  state: { message: "重定向提示信息" },
  replace: true
});

总结

React Router v6 对重定向机制进行了重大改进,主要变化包括:

  1. 使用 Navigate 组件替代 Redirect 组件
  2. 使用 useNavigate hook 替代 useHistory hook
  3. 推荐使用 replace 选项保持历史记录清洁
  4. 通配符路由 * 用于处理未匹配的路由

通过掌握这些技巧,你可以轻松地在 React Router v6 中实现各种重定向需求,创建更流畅的用户体验。