React Router v6中如何进行重定向?

193

我正在尝试升级到React Router v6 (react-router-dom 6.0.1)。

这是我的更新后的代码:

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

<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/lab" element={<Lab />} />
    <Route render={() => <Navigate to="/" />} />
  </Routes>
</BrowserRouter>

最后一个 Route 会将其余的路径重定向到 /.

然而,我遇到了一个错误

TS2322: 类型 '{ render: () => Element; }' 不能分配给类型 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)'。属性 'render' 在类型 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)' 中不存在。

但是,根据文档,它确实有 Routerender。我该如何正确使用它?


4
这似乎是文档中的一个错误。请注意,在上面的部分中已经弃用了render并推荐使用children,但是您正在阅读的部分似乎是关于从v5升级到v5.1,他们只是在v6中删除了render。看起来 <Route element={<Navigate to="/" />} /> 是新样式 - Bergi
https://gist.github.com/mjackson/b5748add2795ce7448a366ae8f8ae3bb#not-server-rendering - Bergi
当您最终升级到v6时,请将<Route render={() => ...}>转换为<Route element={...}>,这样就可以完成了。 - Bergi
感谢@Bergi,我通过一些更新成功了:<Route path="*" element={<Navigate to="/" />} />,请随意发布为答案! - Hongbo Miao
11个回答

352

我认为你应该采用"无匹配路由"的方法。

请查看文档:添加"无匹配"路由

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属性。这样可以避免用户点击后出现额外的重定向。

如果您想在React组件外或不使用hooks进行重定向,请查看此答案 - totymedli
1
如果“/”是其他路由的父级路由,该怎么办?如何防止“/”本身成为可导航到的路由?而是在“home”作为“/”下的子级时将“/”重定向到“/home”? - Douglas Gaskell
值得注意的是,这个静态路由没有SSR支持。 - Neil
@RodolfoSilva 但是如果我们还想添加一个NotFound页面,那么我们应该在NotFound中添加什么路径? - Kashif Ali
1
@KashifAli,如果是这样的话,您应该用自定义的“未找到”屏幕替换导航组件。我认为您将无法同时使用通配符路径。但是,您可以使用嵌套方法来限制用户何时应在某个路径内重定向。 - RodolfoSilva
1
有关Navigate和Replace的API文档在哪里可以找到?看来我应该停留在文档阶段,但不知怎么就来到了这里。 - ColdHands

74

我发现另一种方法来做这件事:

import { useNavigate } from "react-router-dom";
let navigate = useNavigate();

useEffect(() => {
   if (LoggedIn){
      return navigate("/");
   }
},[LoggedIn]);

参见概览,导航


3
它说 useNavigator 只能在路由器的上下文中使用,不能单独使用。 - Zain Sadaqat
将此组件放置在适当的路由器组件内使用:示例:<BrowserRouter>{...在此引用本答案中的组件的路由}</BrowserRouter> - Mattwmaster58

14

创建 RequireAuth.tsx 文件

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

export function RequireAuth({ children }: { children: JSX.Element }) {
  let { user } = useAuth();
  let location = useLocation();

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

导入所需组件以使用私有路由器:

import { Routes as Switch, Route } from "react-router-dom";

import { RequireAuth } from "./RequireAuth";
import { SignIn } from "../pages/SignIn";
import { Dashboard } from "../pages/Dashboard";

export function Routes() {
  return (
    <Switch>
      <Route path="/" element={<SignIn />} />
      <Route
        path="/dashboard"
        element={
          <RequireAuth>
            <Dashboard />
          </RequireAuth>
        }
      />
    </Switch>
  );
}


8

适用于 react-router 版本 6

编辑后的新示例----->(更加简单易读)

import {BrowserRouter as Router,Routes,Route} from 'react-router-dom';
import Home from '../NavbarCompo/About';
import Contact from '../NavbarCompo/Contact';
import About from '../NavbarCompo/About';
import Login  from '../NavbarCompo/Login';
import Navbar from '../Navbar/Navbar';
import Error from '../pages/error';
import Products  from '../pages/products';
import Data from '../NavbarCompo/Data';

const Roter=()=>{
    return (
    <Router>

            <Navbar />
        <Routes>
            
            <Route path='/' element={<Home />} />
            <Route path='/about' element={<About />} />
            <Route path='/contact' element={<Contact />} />
            <Route path='/login' element={<Login />} />
            <Route path='/product/:id' element={<Products />} />
            <Route path='/data' element={<Data />} />
            <Route path ='*' element={<Error />} />
        </Routes>


    </Router>
    )
}
export default Roter;

看一下示例

import React from "react";
import Form from "./compo/form";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider, Route,Routes,Navigate } from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Form />
  },
  {
    path: "/about",
    element: <h1>hola amigo,you are in about section</h1>
  },
  {
    path:"*",
    element:<Navigate to="/" replace />
  }
]);

const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(
  <React.StrictMode>
    <RouterProvider router={router}></RouterProvider>
  </React.StrictMode>
);

看这个 https://reactrouter.com/en/main/start/overview


我是指针对react-router v6,看看这个网站https://reactrouter.com/en/main/start/overview - Mr.Kumawat Lalit

8

在 React 的第五个版本中(即 react-router-dom),我们使用的是 Redirect 组件。但是在 React 的第六个版本中,这个组件被更新为 Navigate 组件。

我们可以在这些组件中传递 replace 属性,以避免在单击后退和前进选项时出现不必要的重定向。

下面附有用法演示:

<Route  path="/" element={user ? <Home /> : <Register />} />
<Route path="/login" element={user ? <Navigate to="/" replace /> :  <Login />}  />
<Route path = "/register" element={user ? <Navigate to="/" replace /> :  <Register />} />

5
import { useNavigate } from "react-router-dom";
import { Button } from "@mui/material";

const component =()=>{

    const navigate = useNavigate();

    const handelGoToLogin = () => {
        navigate('/auth/login')
    }

    return(<>
        //.........
    
        <Button onClick={handelGoToLogin} variant="outlined" color="primary" size="large" fullWidth>
             Back
        </Button>

    </>)
}

5
      <BrowserRouter>
        <Routes>
          <Route path="home" element={<Home />} />
          <Route path="about" element={<About />} />
          <Route index element={<Navigate to="/home" replace />} />
        </Routes>
      </BrowserRouter>

4
我遇到了一个问题,如果用户在没有登录的情况下尝试访问仪表盘,我需要将用户重定向到/login页面。起初,我使用了Navigate('/login')方法,但这并不是正确的方式,因为它会先渲染页面,然后再重定向到登录页面。所以我采用了另一种方法,具体如下。
    const auth  = useContext(AuthContext);

if(!auth?.loggedin){
  
    return <Navigate to='/login'></Navigate>
}return children;

3

你可以使用 react-router-dom 中的 Navigate 组件来实现与 Redirect 相同的效果。首先,import { Navigate } from 'react-router-dom' 这是一个例子:

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

replace 用于替换当前的历史记录条目,而不是添加新的条目。


2
import { useState } from "react"
import { Navigate } from "react-router-dom"
const [login, setLogin] = useState(true)
return (<>
{!login && <Navigate to="/login" />}
<>)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接