如何在react-router-dom v6中返回上一个路由

140
在早期版本中,我们可以使用历史记录(history)返回到先前的路由(previous route)。
history.goBack()

我该如何在 react-router-domv6版本中实现这个目标?

1
看起来可能是关于useNavigate的内容,链接为https://github.com/ReactTraining/react-router/blob/dev/docs/advanced-guides/migrating-5-to-6.md#use-navigate-instead-of-history - Zac Anger
2
这很棒。但是你如何使用浏览器的后退和前进按钮?由于某些原因,它们无法检测到堆栈中的先前路由。 - yosemeti
8个回答

297

尝试这种方法

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

function YourApp() {
  const navigate = useNavigate();

  return (
    <>
      <button onClick={() => navigate(-1)}>go back</button>
    </>
  );
}

3
你好,我有一个问题:如果没有上一页,怎么让它跳转到主页呢? - Peterlits Zo
4
@PeterlitsZo 使用 navigate("/")。 (说明:这是一条代码指令,意思是使用React Navigation库中的navigate函数跳转到路径为"/"的页面。) - Pedro Cunha
9
@PedroCunha,你怎么知道历史上没有先前的一页? - Titenis
我建议您使用自定义钩子来实现这个功能。它看起来像这样: 如果(prevPage存在 && prevPageUrl包含您的域名URL){跳转到上一页} 否则 {跳转到主页} - Wale

56

在V6中,

import { useNavigate } from 'react-router-dom';
 
function App() {
  const navigate = useNavigate();
 
  return (
    <>
      <button onClick={() => navigate(-2)}>Go 2 pages back</button>
      <button onClick={() => navigate(-1)}>Go back</button>
      <button onClick={() => navigate(1)}>Go forward</button>
      <button onClick={() => navigate(2)}>Go 2 pages forward</button>
    </>
  );
}

虽然某些浏览器不支持此功能。 - RJA

42

以防万一,如果有人像我一样尝试导航回去或者在无法导航回去的情况下导航到其他地方(例如在新标签页中打开链接),似乎没有任何办法在react-router v6中验证历史记录。 但是看起来你可以访问 window.history.state,它有一个 idx 属性,如果你在历史堆栈的开头,那么该属性为零。

可能还有一些坑点我没有遇到,但这对我有用:

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

// ...

const navigate = useNavigate();

// ...

if (window.history.state && window.history.state.idx > 0) {
    navigate(-1);
} else {
    navigate('/', { replace: true }); // the current entry in the history stack will be replaced with the new one with { replace: true }
}

很遗憾,这并非百分之百可靠。保持怀疑态度。即使在应用程序内部进行路由时,window.history.state.idx 也不总是定义的。 - Taylor Buckner
@TaylorBuckner,你能给个例子说明什么情况下会导致它变成未定义吗?我在几个React应用中都使用过它,但还没有遇到过它变为未定义的情况。 - Gee

18

在旧版本的react-router-dom中存在pop函数。

你可以像这样调用它们:

const history = useHistory();
history.pop()

现在在v6中,您可以使用useNavigate函数。

const navigate = useNavigate();
navigate(-1) // you will go one page back
navigate(-2) // you will go two pages back

7
翻译:花了20分钟查阅文档,但是这个魔法数字的方法并没有找到。谢谢。 - Daniel Baranowski
@DanielBaranowski 很高兴我能帮到你!:D - Abdulrahim Klis
我猜他们更新了文档,因为现在似乎在那里列出了魔数方法的内容... https://reactrouter.com/en/v6.3.0/api#usenavigate - cowley05
1
使用 history.goBack() 代替 pop(),因为它不起作用。 - Lalit Fauzdar
@LalitFauzdar 这取决于您使用的版本。 - Abdulrahim Klis

11

在react-router Links v6中,还有一种使用delta(数字)的方法:

const BackButton = () => {
  return (
    <Link to={-1}>
      Back
    </Link>
  );
};

很不幸,在 TypeScript 中存在类型错误,Link 组件不接受数字类型,但它仍然可以正常工作。


1
也适用于 NavLink: <NavLink to={-1}>返回</NavLink> - brunshte
7
对于任何想在TypeScript中使用它的人:你可以写成-1 as any,而不是仅仅写成-1 - Amin_mmz

5

如果您想返回或者前往其他页面,可以尝试以下操作:

 <button onClick={() => navigate(-1) || navigate('/dashboard')}>
    Go back or Dashboard
  </button>

聪明!你知道在文档中我可以参考这种方法吗? - Null isTrue
您可以在v5到v6迁移中找到navigate(-1)的用法,或者在v6文档中查看。 - Clifford Fajardo
1
我认为这不起作用(这里使用的是react-router-dom@6.4.2),因为navigate返回void。我得到了“无法测试真实性的类型为'void'的表达式”的错误信息。 - Zefir
navigate(-1)返回undefined,因此它将始终导航到'/dashboard'(在react-router-dom 6.8.0中经过测试)。 - mDeram

2

我想要补充的是,有时候在导航至(-1)的条件下会导致错误页面的情况发生,比如在进行授权检查期间的重定向。

import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
navigate(-1);

如果我们想要明确定义一个状态,其中我们有一个先前的页面,我们可以在状态中添加一个“from”属性。
import { useLocation, useNavigate } from 'react-router-dom';
const location = useLocation();
const navigate = useNavigate();
const currentPath = location.pathname;
navigate('/login', { state: { from: currentPath } });

在导航到登录页面之前,我们将路由状态设置为具有“from”属性,该属性等于当前路由。

在登录后加载页面时,我们首先检查状态的“from”属性中是否存储了先前的路由,就像具有一个级别的历史堆栈一样。

  const state = location.state;
  if (state?.from) {
     // Redirects back to the previous unauthenticated routes
     navigate(state?.from);
  else {
     navigate('/main-page');
   }

如果“from”属性为假值,则导航至默认页面。
再次强调,这是一种解决方案,我们明确地定义了先前的路由,而不是依赖于历史记录中的最近项。

-4
import { useEffect } from "react";
import {useNavigate } from "react-router-dom";// react-router-dom v6 version 

const SecondComponent = () =>{
const navigate = useNavigate();
  
useEffect(() => {
    navigate('/secondComponent')
  },[]);

// note: we must have to to provide path like this one 
/*
<Routes>
        <Route path="/" element={<FirstComponent/>} />
        <Route path="/secondComponent" element={<SecondComponent />} />
      </Routes>
*/

  return(
    <>
    <h2 >this is Second page</h2>
    </>
  )
}

export  default SecondComponent;

1
这不是正确的答案。navigate('/secondComponent')导航到另一个页面。要返回,您必须使用navigate(-1) - man.in.the.jukebox
虽然这段代码可能回答了问题,但提供有关它如何以及/或为什么解决问题的附加上下文将改善答案的长期价值。 - nima

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