Skip to content

Instantly share code, notes, and snippets.

@gpltaylor
Last active January 2, 2017 12:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gpltaylor/80e932c859d5e2dd1471555e610fe994 to your computer and use it in GitHub Desktop.
Save gpltaylor/80e932c859d5e2dd1471555e610fe994 to your computer and use it in GitHub Desktop.
import React, { PropTypes } from 'react'
const BEFOREUNLOAD = "beforeunload"; // see: http://stackoverflow.com/questions/39094138/reactjs-event-listener-beforeunload-added-but-not-removed
class NavigationPrompt extends React.Component {
static contextTypes = {
router: PropTypes.object.isRequired
}
static defaultProps = {
when: true
}
block() {
if (!this.teardownPrompt)
this.teardownPrompt = this.context.router.blockTransitions(this.props.message)
}
unblock() {
if (this.teardownPrompt) {
this.teardownPrompt()
delete this.teardownPrompt
}
}
blockUnload(_onbeforeunload) {
if(this._subscribed) { return }
this._subscribed = _onbeforeunload ? _onbeforeunload : this.onbeforeunload;
window.addEventListener(BEFOREUNLOAD, this._subscribed)
}
unblockUnload() {
window.removeEventListener(BEFOREUNLOAD, this._subscribed)
delete this._subscribed
}
componentWillMount() {
if (this.props.when)
this.block()
if (this.props.beforeUnload)
this.blockUnload();
}
onbeforeunload(e) {
var dialogText = "leave"
e.returnValue = dialogText
return dialogText
}
componentWillReceiveProps(nextProps) {
if (nextProps.when === true && this.props.when === false) {
this.block()
} else if (nextProps.when === false && this.props.when === true) {
this.unblock()
}
// props.beforeUnload = Boolean : True
if (nextProps.beforeUnload === true && this.props.beforeUnload === false) {
this.blockUnload()
} else if (nextProps.beforeUnload === false &&
(this.props.beforeUnload === true || typeof this.props.beforeUnload === "function")) {
this.unblockUnload()
}
// props.beforeUnload = function
if (typeof nextProps.beforeUnload === "function") {
this.blockUnload(nextProps.beforeUnload)
}
}
componentWillUnmount() {
this.unblock()
this.unblockUnload()
}
render() {
return null
}
}
if (__DEV__) {
NavigationPrompt.propTypes = {
when: PropTypes.bool,
message: PropTypes.oneOfType([
PropTypes.func,
PropTypes.string
]).isRequired,
beforeUnload: PropTypes.oneOfType([
PropTypes.func,
PropTypes.bool
])
}
}
export default NavigationPrompt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment