尽管可以在阻止通过链接在页面之间导航的同时使用自定义模态组件,但是 在尝试关闭浏览器或重新加载浏览器时无法显示自定义模态。
但是,如果您还可以,则可以使用
history.listento并阻止导航。我为此编写了一个通用的HOC来解决此用例。
在下面的代码中,白名单中的路径名是您希望其他人导航到而不显示提示的路径名
import React from 'react';import { withRouter } from 'react-router';import _ from 'lodash';const navigationpromptFactory = ({ prompt }) => { const initialState = { currentLocation: null, targetLocation: null, isOpen: false }; class Navigationprompt extends React.Component { static defaultProps = { when: true }; state = initialState; componentDidMount() { this.block(this.props); window.addEventListener('beforeunload', this.onBeforeUnload); } componentWillReceiveProps(nextProps) { const { when: nextWhen, history: nextHistory, whiteListedPathnames: nextWhiteListedPaths } = nextProps; const { when, history, whiteListedPathnames } = this.props; if ( when !== nextWhen || !_.isEqual(nextHistory.location, history.location) || !_.isEqual(whiteListedPathnames, nextWhiteListedPaths) ) { this.unblock(); this.block(nextProps); } } componentWillUnmount() { this.unblock(); window.removeEventListener('beforeunload', this.onBeforeUnload); } onBeforeUnload = e => { const { when } = this.props; // we can't override an onBeforeUnload dialog // eslint-disable-next-line // https://stackoverflow.com/questions/276660/how-can-i-override-the-onbeforeunload-dialog-and-replace-it-with-my-own if (when) { // support for custom message is no longer there // https://www.chromestatus.com/feature/5349061406228480 // eslint-disable-next-line // https://stackoverflow.com/questions/38879742/is-it-possible-to-display-a-custom-message-in-the-beforeunload-popup // setting e.returnValue = "false" to show prompt, reference below //https://github.com/electron/electron/issues/2481 e.returnValue = 'false'; } }; block = props => { const { history, when, whiteListedPathnames = [], searchQueryCheck = false } = props; this.unblock = history.block(targetLocation => { const hasPathnameChanged = history.location.pathname !== targetLocation.pathname; const hasSearchQueryChanged = history.location.search !== targetLocation.search; const hasUrlChanged = searchQueryCheck ? hasPathnameChanged || hasSearchQueryChanged : hasPathnameChanged; const isTargetWhiteListed = whiteListedPathnames.includes( targetLocation.pathname ); const hasChanged = when && hasUrlChanged && !isTargetWhiteListed; if (hasChanged) { this.setState({ currentLocation: history.location, targetLocation, isOpen: true }); } return !hasChanged; }); }; on/confirm/i = () => { const { history } = this.props; const { currentLocation, targetLocation } = this.state; this.unblock(); // replacing current location and then pushing navigates to the target otherwise not // this is needed when the user tries to change the url manually history.replace(currentLocation); history.push(targetLocation); this.setState(initialState); }; onCancel = () => { const { currentLocation } = this.state; this.setState(initialState); // Replacing the current location in case the user tried to change the url manually this.unblock(); this.props.history.replace(currentLocation); this.block(this.props); }; render() { return ( <prompt {...this.props} isOpen={this.state.isOpen} onCancel={this.onCancel} on/confirm/i={this.on/confirm/i} /> ); } } return withRouter(Navigationprompt);};export { navigationpromptFactory };为了使用以上内容,您可以简单地提供自定义的提示模式,例如
const Navigationprompt = navigationpromptFactory({prompt: alertDialog }); const whiteListedPathnames = [`${match.url}/abc`, match.url]; <Navigationprompt when={isEditingPlan} cancelLabel={'Stay'} confirmLabel={'Leave'} whiteListedPathnames={whiteListedPathnames} title={'Leave This Page'} > <span> Unsaved Changes may not be saved </span> </Navigationprompt>


