使用 react-router 检测用户离开页面

新手上路,请多包涵

我希望我的 ReactJS 应用程序在离开特定页面时通知用户。特别是提醒他/她执行操作的弹出消息:

“更改已保存,但尚未发布。现在做吗?”

我应该在全球范围内触发 react-router ,还是可以从反应页面/组件中完成?

我还没有找到关于后者的任何东西,我宁愿避免第一个。除非它当然是常态,但这让我想知道如何在不必向用户可以访问的每个其他可能页面添加代码的情况下做这样的事情。

欢迎任何见解,谢谢!

原文由 Barry Staes 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.6k
2 个回答

react-router v4 引入了一种使用 Prompt 阻止导航的新方法。只需将其添加到您要阻止的组件中:

 import { Prompt } from 'react-router'

const MyComponent = () => (
  <>
    <Prompt
      when={shouldBlockNavigation}
      message='You have unsaved changes, are you sure you want to leave?'
    />
    {/* Component JSX */}
  </>
)

这将阻止任何路由,但不会阻止页面刷新或关闭。要阻止它,您需要添加它(根据需要使用适当的 React 生命周期进行更新):

 componentDidUpdate = () => {
  if (shouldBlockNavigation) {
    window.onbeforeunload = () => true
  } else {
    window.onbeforeunload = undefined
  }
}

onbeforeunload 有多种浏览器支持。

原文由 jcady 发布,翻译遵循 CC BY-SA 4.0 许可协议

在 react-router v2.4.0 或之前和之前 v4 有几个选项

  1. 添加功能 onLeaveRoute
  <Route
      path="/home"
      onEnter={ auth }
      onLeave={ showConfirm }
      component={ Home }
    >


  1. 使用函数 setRouteLeaveHook 用于 componentDidMount

您可以在离开带有 leave hook 的路由之前防止发生转换或提示用户。

 const Home = withRouter(
  React.createClass({

    componentDidMount() {
      this.props.router.setRouteLeaveHook(this.props.route, this.routerWillLeave)
    },

    routerWillLeave(nextLocation) {
      // return false to prevent a transition w/o prompting the user,
      // or return a string to allow the user to decide:
      // return `null` or nothing to let other hooks to be executed
      //
      // NOTE: if you return true, other hooks will not be executed!
      if (!this.state.isSaved)
        return 'Your work is not saved! Are you sure you want to leave?'
    },

    // ...

  })
)

请注意,此示例使用了 withRouter 中引入的高阶组件 v2.4.0.

然而,当手动更改 URL 中的路由时,这些解决方案并不能很好地工作

在某种意义上说

  • 我们看到确认 - 好的
  • 包含页面不重新加载 - 好的
  • URL 没有改变 - 不行

对于 react-router v4 使用提示或自定义历史记录:

然而在 react-router v4 中,在 Prompt from’react-router 的帮助下更容易实现

根据文档

迅速的

用于在离开页面之前提示用户。当您的应用程序进入应阻止用户离开的状态时(例如表单未填写一半),呈现 <Prompt>

>  import { Prompt } from 'react-router'
>
> <Prompt
>   when={formIsHalfFilledOut}
>   message="Are you sure you want to leave?"
> />
>
> ```
>
> **消息:字符串**
>
> 当用户尝试离开时提示用户的消息。
>
> ```
>  <Prompt message="Are you sure you want to leave?"/>
>
> ```
>
> **消息:功能**
>
> 将调用用户尝试导航到的下一个位置和操作。返回一个字符串以向用户显示提示或返回 true 以允许转换。
>
> ```
>  <Prompt message={location => (
>   `Are you sure you want to go to ${location.pathname}?`
> )}/>
>
> ```
>
> **何时:布尔**
>
> 您可以随时渲染它,但传递 `when={true}` 或 `when={false}` 以防止或允许导航,而不是有条件地在守卫后面渲染 `<Prompt>` 。

在您的渲染方法中,您只需根据需要按照文档中的说明添加它。

**更新:**

如果您希望在用户离开页面时执行自定义操作,您可以使用自定义历史记录并配置您的路由器

**历史.js**

import createBrowserHistory from ‘history/createBrowserHistory’ export const history = createBrowserHistory()

… import { history } from ‘path/to/history’;


然后在你的组件中你可以使用 `history.block` 就像

import { history } from ‘path/to/history’; class MyComponent extends React.Component { componentDidMount() { this.unblock = history.block(targetLocation => { // take your action here return false; }); } componentWillUnmount() { this.unblock(); } render() { //component render here } }

”`

原文由 Shubham Khatri 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进