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
React hooks
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
once (on component mount), and sets the event handler to be an anonymous function that will call cb.current
(if it's defined), 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 = (...args) => cb.current?.(...args);
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>
);
};
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…