I have a react component like :
import React, { PropTypes, Component } from 'react'
class MyComponent extends Component {
componentDidMount() {
window.addEventListener("beforeunload", function (event) {
console.log("hellooww")
event.returnValue = "Hellooww"
})
}
componentWillUnmount() {
window.removeEventListener("beforeunload", function (event) {
console.log("hellooww")
event.returnValue = "Hellooww"
})
}
render() {
return (
<div>
Some content
</div>
)
}
}
export default MyComponent
Here event lister is added to the component. When I refresh the page it gives me pop up asking to leave the page.
But when I go to another page and do refresh it again shows the same pop-up.
I am removing the eventListener
from the component on componentWillUnmount
. Then why it is not being removed?
How can I remove the beforeunload
event on other pages?
The removeEventListener
should get the reference to the same callback that was assigned in addEventListener
. Recreating the function won't do. The solution is to create the callback elsewhere (onUnload
in this example), and pass it as reference to both addEventListener
and removeEventListener
:
import React, { PropTypes, Component } from 'react';
class MyComponent extends Component {
onUnload = e => { // the method that will be used for both add and remove event
e.preventDefault();
e.returnValue = '';
}
componentDidMount() {
window.addEventListener("beforeunload", this.onUnload);
}
componentWillUnmount() {
window.removeEventListener("beforeunload", this.onUnload);
}
render() {
return (
<div>
Some content
</div>
);
}
}
export default MyComponent
You can abstract the beforeunload
event handling to a custom hook with the useRef
, and useEffect
hooks.
The custom hook useUnload
receives a function (fn
) and assigns it to the current ref. It calls useEffect
, and sets the event handler, and returns a cleanup function to remove the event handler, when the component is removed.
import { useRef, useEffect } from 'react';
const useUnload = fn => {
const cb = useRef(fn); // init with fn, so that type checkers won't assume that current might be undefined
useEffect(() => {
cb.current = fn;
}, [fn]);
useEffect(() => {
const onUnload = cb.current;
window.addEventListener("beforeunload", onUnload);
return () => window.removeEventListener("beforeunload", onUnload);
}, []);
};
export default useUnload;
Usage:
const MyComponent = () => {
useUnload(e => {
e.preventDefault();
e.returnValue = '';
});
return (
<div>
Some content
</div>
);
};