在 react-router v2.4.0 或以上以及v4 之前有几个选项
- Add function
onLeave for Route
<Route
path="/home"
onEnter={ auth }
onLeave={ showConfirm }
component={ Home }
>
- Use function
setRouteLeaveHook for componentDidMount
您可以在使用离开钩子离开路线之前阻止转换发生或提示用户。
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?'
},
// ...
})
)
请注意,此示例使用了v2.4.0. 中引入的withRouter 高阶组件
但是,当手动更改 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?"/>
消息:函数
将调用用户的下一个位置和操作
试图导航到。返回一个字符串以向
user 或 true 以允许转换。
<Prompt message={location => (
`Are you sure you want to go to ${location.pathname}?`
)}/>
何时:布尔
不是有条件地在守卫后面渲染<Prompt>,而是
始终可以渲染它,但将 when={true} 或 when={false} 传递给
相应地阻止或允许导航。
在您的渲染方法中,您只需要根据您的需要按照文档中的说明添加它即可。
更新:
如果您希望在用户离开页面时执行自定义操作,您可以使用自定义历史记录并配置您的路由器,例如
history.js
import createBrowserHistory from 'history/createBrowserHistory'
export const history = createBrowserHistory()
...
import { history } from 'path/to/history';
<Router history={history}>
<App/>
</Router>
然后在你的组件中你可以使用history.block like
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
}
}