Skip to content

Instantly share code, notes, and snippets.

@bummzack
Created June 28, 2017 19:33
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save bummzack/a586533607ece482475e0c211790dd50 to your computer and use it in GitHub Desktop.
Save bummzack/a586533607ece482475e0c211790dd50 to your computer and use it in GitHub Desktop.
A replacement component for the react-router `Prompt`.
import React from 'react';
import {withRouter} from 'react-router-dom';
import PropTypes from 'prop-types';
/**
* A replacement component for the react-router `Prompt`.
* Allows for more flexible dialogs.
*
* @example
* <NavigationPrompt when={this.props.isDirty}>
* {(isOpen, onConfirm, onCancel) => (
* <Modal show={isOpen}>
* <div>
* <p>Do you really want to leave?</p>
* <button onClick={onCancel}>Cancel</button>
* <button onClick={onConfirm}>Ok</button>
* </div>
* </Modal>
* )}
* </NavigationPrompt>
*/
class NavigationPrompt extends React.Component
{
constructor(props) {
super(props);
this.state = {nextLocation: null, openModal: false};
this.onCancel = this.onCancel.bind(this);
this.onConfirm = this.onConfirm.bind(this);
}
componentDidMount() {
this.unblock = this.props.history.block((nextLocation) => {
if (this.props.when) {
this.setState({
openModal: true,
nextLocation: nextLocation
});
}
return !this.props.when;
});
}
componentWillUnmount() {
this.unblock();
}
onCancel() {
this.setState({nextLocation: null, openModal: false});
}
onConfirm() {
this.navigateToNextLocation();
}
navigateToNextLocation() {
this.unblock();
this.props.history.push(this.state.nextLocation.pathname);
}
render() {
return (
<div>
{this.props.children(this.state.openModal, this.onConfirm, this.onCancel)}
</div>
);
}
}
NavigationPrompt.propTypes = {
when: PropTypes.bool.isRequired,
children: PropTypes.func.isRequired,
};
export default withRouter(NavigationPrompt);
@akrigline
Copy link

When I use my browser's Back button, the modal pops up for a split second and then immediately disappears. Is this something history.block can't handle well?

@ZacharyRSmith
Copy link

@akrigline, we have (a little) more info on your issue here

tl;dr: we still don't know what causes it, but it happens with some setups but not others. @cumibulat was able to reproduce when using react-boilerplate but did not reproduce when not using react-boilerplate

@ZacharyRSmith
Copy link

FYI to readers, I've published an adaptation of this to npm: https://www.npmjs.com/package/react-router-navigation-prompt

@aliwaheed51
Copy link

Could You please share any live example of that?

@quantuminformation
Copy link

What's wrong with the original Prompt?

@matthias-ccri
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment