使用React Router处理后退按钮

23
如果用户浏览到 www.example.com/one 并点击返回按钮,我希望将其重定向到 www.example.com。我认为这是一个常见的问题,但我尚未找到解决方案。

9
我不认为这就是后退按钮的工作方式…用户应该先进入www.example.com,然后导航到www.example.com/one,当它按下“后退”按钮时,返回到www.example.com。 - Martín Zaragoza
1
不使用浏览器的后退按钮。但是想象一下这种情况,您在亚马逊上订购了一个物品,并且订单详细信息发送到您的电子邮件中,当您单击“查看订单详细信息”时,它会带您转到amazon.com/order/:orderID,然后如果他点击后退按钮,应该导航到amazon.com而不是返回电子邮件。如何做到这一点? - holla
10个回答

34

Hooks 版本(React 16.8+):

最简版本。

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

export const Item = () => {
    let history = useHistory();
    return (
        <>
          <button onClick={() => history.goBack()}>Back</button>
        </>
    );
};

67
我相信这个问题是指浏览器的“返回”按钮。开发者为什么要在应用中建立自己的“返回”按钮,当浏览器已经有一个“返回”按钮了呢,这超出了我的理解。 - Johann
8
是的,它的功能与浏览器的后退按钮完全相同。但是,如果浏览器没有后退按钮怎么办?最完美的例子就是在渐进式Web应用程序中。(不是浏览器但) - Hunter
1
不使用浏览器的回退按钮,但是想象一下这种情况:当你在亚马逊订购物品并且订单详情发送到你的电子邮件时,只要你点击“查看订单详情”,就会进入到amazon.com/order/:orderID页面。然后,如果用户点击“返回”按钮,应该导航回到amazon.com而不是回到电子邮件。如何实现? - holla
2
在这种情况下,您可以简单地将链接放到amazon.com。 - Hunter
这不适用于浏览器的后退按钮。我在 https://dev59.com/4lQK5IYBdhLWcg3wUOZ5#66046495 中添加了一个解决方案。 - JeanAlesi
1
@AndroidDev 我知道这是一个旧评论,但为了回答你的问题,我在桌面和移动应用程序中使用React。 - Cory Fail

24
react-router-dom v6 中, useHistory()useNavigate() 替代了。所以使用 useNavigate() 代替 useHistory() 就可以了。
import { useNavigate} from "react-router-dom";

export const Item = () => {
    let navigate = useNavigate();
    return (
        <>
          <button onClick={() => navigate(-1)}>Back</button> 
        </>
    );
};

了解更多关于useNavigate的内容,请访问:https://reactrouter.com/docs/en/v6/hooks/use-navigate


6

你可以尝试两种选项,一种是使用push方法,另一种是使用路由的历史记录中的goBack方法。通常,如果您直接通过Route方法路由组件或将历史记录属性传递给子组件并使用它,则将提供历史记录props。

以下是示例代码:

this.props.history.push('/') //this will go to home page

or

this.props.history.goBack() //this will go to previous page

针对您的问题,您可以尝试使用push方法,并提供您要移动到的确切URL。

如需更多参考,请访问https://reacttraining.com/react-router/web/api/history


3

你想要的是这个:

假设一个人进入了你网站的某一页,比如:www.yoursite.com/category/books/romeo-and-juliet

在这个页面,你想要显示一个“返回”按钮,它链接到上一级目录,即:www.yoursite.com/category/books/

这就是我们在vBulletin论坛等地方著名的面包屑导航系统。

这里是一个基本解决方案:

Original Answer翻译成"最初的回答"

let url = window.location.href;
let backButtonUrl = "";
if (url.charAt(url.length - 1) === "/") {
  backButtonUrl = url.slice(0, url.lastIndexOf("/"));
  backButtonUrl = backButtonUrl.slice(0, backButtonUrl.lastIndexOf("/"));
} else {
  backButtonUrl = url.slice(0, url.lastIndexOf("/"));
}

基本上它的作用是: 1. 从浏览器中获取当前URL 2. 检查链接末尾是否有“/”(斜杠)。 a. 如果有:删除斜杠,并删除最后一个斜杠之后的所有内容 b. 如果没有:删除最后一个斜杠之后的所有内容。
您可以使用{backButtonUrl}作为返回按钮链接。
注意:它与React Router、history等无关。 注意2:假设您使用的链接结构是www.site.com/word/letter/character 如果您想在react-router-dom库中使用它,则需要像这样设置您的URL变量: let url = this.props.match.url;

2
我找到了一个解决方案。它不太美观,但是它有效。
class Restaurant extends Component {
    constructor(props) {
        super(props);
        this.props.history.push('/');
        this.props.history.push(this.props.match.url);
    }
    ...

2
我今天也遇到了同样的问题。我正在处理的一个应用程序中有以下流程:
  1. 用户填写注册表格
  2. 用户进入信用卡“付款页面”
  3. 当支付成功时,用户会看到“付款确认”页面。
我想防止用户从“付款确认”(3)页面返回到支付流程中的任何先前步骤(1和2)。
最好的方法是不使用路由来控制显示哪些内容,而是使用状态。如果您无法承担此费用, 我找到了两种解决问题的实际方法:
  1. 使用React-Router:
  • 当您点击后退按钮时,React Router的历史对象将如下所示:

enter image description here

  • 当你使用 history.push 访问任何页面时,记录你正在访问的页面在状态中
  • 创建一个装饰器、HOC 或者你喜欢的任何类型的包裹器来包裹 React-Router 的 Route 组件。在这个组件中:如果 history.action === "POP" 并且 "history.state.lastVisited === <some page with back navigation disabled>",那么你应该使用 history.replace 重定向用户到 /home 页面
  1. 另一种方法是直接转到 /home 页面: 使用 history.action 来检测是否使用了后退按钮,然后:
  • 将 location.href 更改为你想要访问的页面
  • 调用 location.reload()。这将重新加载应用程序,并且历史记录将被重置

1
我找了很久!你可以在导航方法中使用状态选项:
导航(route, {state: {canBack: true}})
然后在你的返回按钮中引用。
const navigate = useNavigate();
const location = useLocation();
    
const goBack = () => {
  navigate(-"1);
}

location.state?.canBack // check if user can back

0

我们想为我们的React应用程序找到类似的解决方案,但不幸的是这是我们想出的最好的解决方案。当我们的用户在移动设备上从广告或referrer着陆到我们网站上的特定页面时,这尤其有帮助。

这在我们的主要routes.tsx文件中。

 useEffect(() => {
    // The path that the user is supposed to go to
    const destinationPath = location.pathname;

    // If our site was opened in a new window or tab and accessed directly
    // OR the page before this one was NOT a page on our site, then...
    if (
      document.referrer === window.location.href ||
      document.referrer.indexOf(window.location.host) === -1
    ) {
      // Replaces the current pathname with the homepage
      history.replace("/");

      // Then pushes to the path the user was supposed to go to
      history.push(destinationPath);
    }
  }, []);

现在,当用户按下返回按钮时,它会将用户带回我们的主页,而不是被困在他们所在的“嵌套”路由中。

注意:这种实现方式存在一些小问题。我们的应用程序也是Cordova应用程序,因此我们需要有自己的返回按钮。这种实现方式可以很好地与我们自己的返回按钮配合使用,但似乎无法与本机浏览器的返回按钮配合使用;因此,它对我们的需求非常有效。


为其他人添加一条注释。history.listen和setState很好地配合使用(即使在v6下,但您需要使用history包)。 - Kobato

0

浏览器的返回按钮是基于你的路由历史记录工作的。它不会调用你程序化处理的路由。这就是我们应该使用React Router来保持历史堆栈的地方。如果你在路由'/',然后推入'/home'。当你按下浏览器的返回按钮时,它将弹出'/home'并返回到'/'

即使你实现了Button组件来实现返回功能,并使用React Router的history props。相信我,你必须仔细管理你的导航,以适当地维护浏览器历史堆栈。这样它才能像按下浏览器的返回按钮或你的应用程序Button一样正常工作。希望这对你有所帮助。


0

你可以使用 ../ 或者 useNavigate 来实现这个功能。

import { Link } from "react-router-dom";
.
.
.
<Link to="../" relative="path"> Back </Link>

或者(推荐)

import { useNavigate} from "react-router-dom";
.
.
.
const navigate = useNavigate();
.
.
.
<button onClick={() => navigate(-1)}> Back </button> 

源代码: React Router v6.11.1


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