如何使用react router dom v6控制浏览器后退按钮?

Esa*_*wan 20 reactjs react-router-dom

我一直在寻找这个问题并找到了它,但他们正在使用类组件和 React router dom v5

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

Esa*_*wan 14

经过漫长的探索如何做到这一点后,我终于想出了这个解决方案

window.onpopstate = () => {
  navigate("/");
}
Run Code Online (Sandbox Code Playgroud)


Dre*_*ese 14

React-Router-Dom v6.0+ 路由器

\n

如果您只是想在发生后退导航( POP 操作)时运行一个函数,那么一个可能的解决方案是使用导出的NavigationContext.

\n

例子:

\n
import { UNSAFE_NavigationContext } from "react-router-dom";\n\nconst useBackListener = (callback) => {\n  const navigator = useContext(UNSAFE_NavigationContext).navigator;\n\n  useEffect(() => {\n    const listener = ({ location, action }) => {\n      console.log("listener", { location, action });\n      if (action === "POP") {\n        callback({ location, action });\n      }\n    };\n\n    const unlisten = navigator.listen(listener);\n    return unlisten;\n  }, [callback, navigator]);\n};\n
Run Code Online (Sandbox Code Playgroud)\n

用法:

\n
import { useNavigate } from \'react-router-dom\';\nimport { useBackListener } from \'../path/to/useBackListener\';\n\n...\n\nconst navigate = useNavigate();\n\nuseBackListener(({ location }) => {\n  console.log("Navigated Back", { location });\n  navigate("/", { replace: true });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

如果UNSAFE_NavigationContext您希望避免使用上下文,那么另一种方法是创建一个自定义路由,该路由可以使用自定义历史对象(即 fromcreateBrowserHistory)并使用普通的History.listen。详细信息参阅我的回答。

\n

带打字稿

\n
import { useEffect, useContext } from "react";\nimport { NavigationType, UNSAFE_NavigationContext } from "react-router-dom";\nimport { History, Update } from "history";\n\nconst useBackListener = (callback: (...args: any) => void) => {\n  const navigator = useContext(UNSAFE_NavigationContext).navigator as History;\n\n  useEffect(() => {\n    const listener = ({ location, action }: Update) => {\n      console.log("listener", { location, action });\n      if (action === NavigationType.Pop) {\n        callback({ location, action });\n      }\n    };\n\n    const unlisten = navigator.listen(listener);\n    return unlisten;\n  }, [callback, navigator]);\n};\n
Run Code Online (Sandbox Code Playgroud)\n

useNavigationType如果您只想知道是否发生了 POP 操作,您也可以使用该挂钩。

\n
import {\n  useLocation,\n  useNavigationType,\n  NavigationType\n} from "react-router-dom";\n\nconst useBackListener = (callback) => {\n  // Ref is used to handle any React.StrictMode double-mounting\n  const initialRender = React.useRef(true);\n\n  const location = useLocation();\n  const navigationType = useNavigationType();\n\n  useEffect(() => {\n    if (!initialRender.current && navigationType === NavigationType.Pop) {\n      initialRender.current = false;\n      callback({ location });\n    }\n\n  }, [callback, location, navigationType]);\n};\n
Run Code Online (Sandbox Code Playgroud)\n

React-Router-Dom v6.4+ 数据路由器

\n

对于数据路由器,您可以使用(当前仍在使用的router.subscribe处理程序来替换history.listen。如有必要,它也可以轻松抽象为自定义。请注意,subscribe当前不是“公共”API 的一部分,并且存在类似的情况NavigationContext,并且HistoryRouter可以随时将其删除。有关更多详细信息/说明,请参阅此 Github问题。

\n

例子:

\n
const router = createBrowserRouter([\n  ...\n]);\n\nexport default function App() {\n  React.useEffect(() => {\n    router.subscribe((state) => {\n      if (state.historyAction === NavigationType.Pop) {\n        ....\n      }\n    });\n  }, []);\n\n  return <RouterProvider router={router} />;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

示例state值:

\n
const router = createBrowserRouter([\n  ...\n]);\n\nexport default function App() {\n  React.useEffect(() => {\n    router.subscribe((state) => {\n      if (state.historyAction === NavigationType.Pop) {\n        ....\n      }\n    });\n  }, []);\n\n  return <RouterProvider router={router} />;\n}\n
Run Code Online (Sandbox Code Playgroud)\n