如何用REACT路由器DOM V6控制浏览器的后退按钮?

vs3odd8k  于 2022-09-21  发布在  React
关注(0)|答案(4)|浏览(427)

我一直在寻找这个问题,并找到了它,但他们使用的是类组件和Reaction路由器DOM v5

我想要的是当用户点击浏览器后退按钮时,我会将他们重定向到主页

cpjpxq1n

cpjpxq1n1#

如果您只是想在返回导航(POP操作)发生时运行函数,那么可能的解决方案是使用导出的NavigationContext为其创建自定义挂钩。

示例:

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

const useBackListener = (callback) => {
  const navigator = useContext(UNSAFE_NavigationContext).navigator;

  useEffect(() => {
    const listener = ({ location, action }) => {
      console.log("listener", { location, action });
      if (action === "POP") {
        callback({ location, action });
      }
    };

    const unlisten = navigator.listen(listener);
    return unlisten;
  }, [callback, navigator]);
};

用途:

import { useNavigate } from 'react-router-dom';
import { useBackListener } from '../path/to/useBackListener';

...

const navigate = useNavigate();

useBackListener(({ location }) =>
  console.log("Navigated Back", { location });
  navigate("/", { replace: true });
);

如果您希望避免使用UNSAFE_NavigationContext上下文,那么另一种选择是创建一个可以使用自定义历史记录对象(即来自createBrowserHistory)并使用普通历史记录的定制路由。详情见我的答案here

使用类型脚本更新

import { useEffect, useContext } from "react";
import { NavigationType, UNSAFE_NavigationContext } from "react-router-dom";
import { History, Update } from "history";

const useBackListener = (callback: (...args: any) => void) => {
  const navigator = useContext(UNSAFE_NavigationContext).navigator as History;

  useEffect(() => {
    const listener = ({ location, action }: Update) => {
      console.log("listener", { location, action });
      if (action === NavigationType.Pop) {
        callback({ location, action });
      }
    };

    const unlisten = navigator.listen(listener);
    return unlisten;
  }, [callback, navigator]);
};
kadbb459

kadbb4592#

经过一段漫长的旅程,我终于想出了这个解决方案

window.onpopstate = () => {
  navigate("/");
}
kadbb459

kadbb4593#

对于这种情况,我想出了一个相当健壮的解决方案,只需使用浏览器方法,因为Reaction-Router-V6的API目前在这个部门相当粗略。

我推送一些与当前路线完全相同的虚假历史记录(也就是针对后退按钮的缓冲区)。然后,我监听PopState事件(Back按钮事件),并触发我需要的任何JS,在我的例子中,这会卸载组件。如果组件在没有使用Back按钮的情况下卸载,比如通过屏幕上的按钮或其他逻辑,我们只需使用useEffect的回调来清理我们的虚假历史。哎哟。所以看起来是这样的:

function closeQuickView() {
    closeMe() // do whatever you need to close this component
  }

  useEffect(() => {
    // Add a fake history event so that the back button does nothing if pressed once
    window.history.pushState('fake-route', document.title, window.location.href);

    addEventListener('popstate', closeQuickView);

    // Here is the cleanup when this component unmounts
    return () => {
      removeEventListener('popstate', closeQuickView);
      // If we left without using the back button, aka by using a button on the page, we need to clear out that fake history event
      if (window.history.state === 'fake-route') {
        window.history.back();
      }
    };
  }, []);
mgdq6dx1

mgdq6dx14#

您可以使用RRDV6中的useNavigate钩子返回

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

const App = () => {

    const navigate = useNavigate();
    const goBack = () => navigate(-1);

    return (
        <div>
         ...
         <button onClick={goBack}>Go back</button>
         ...
        </div>
    )
}

export App;

相关问题