When the page refreshes react doesn’t have the chance to unmount the components as normal. Use the window.onbeforeunload
event to set a handler for refresh (read the comments in the code):
class Demo extends React.Component {
constructor(props, context) {
super(props, context);
this.componentCleanup = this.componentCleanup.bind(this);
}
componentCleanup() { // this will hold the cleanup code
// whatever you want to do when the component is unmounted or page refreshes
}
componentWillMount(){
if(dataReady.get(true)){
let logos = this.props.questions[0].data.logos.length > 0 ? this.props.questions[0].data.logos.filter((item) => {
if(item.logo === true && item.location !== ""){
return item;
}
}) : [];
this.setState({ logos });
}
}
componentDidMount(){
window.addEventListener('beforeunload', this.componentCleanup);
}
componentWillUnmount() {
this.componentCleanup();
window.removeEventListener('beforeunload', this.componentCleanup); // remove the event handler for normal unmounting
}
}
useWindowUnloadEffect Hook
I’ve extracted the code to a reusable hook based on useEffect
:
// The hook
const { useEffect, useRef, useState } = React
const useWindowUnloadEffect = (handler, callOnCleanup) => {
const cb = useRef()
cb.current = handler
useEffect(() => {
const handler = () => cb.current()
window.addEventListener('beforeunload', handler)
return () => {
if(callOnCleanup) handler()
window.removeEventListener('beforeunload', handler)
}
}, [callOnCleanup])
}
// Usage example
const Child = () => {
useWindowUnloadEffect(() => console.log('unloaded'), true)
return <div>example</div>
}
const Demo = () => {
const [show, changeShow] = useState(true)
return (
<div>
<button onClick={() => changeShow(!show)}>{show ? 'hide' : 'show'}</button>
{show ? <Child /> : null}
</div>
)
}
ReactDOM.render(
<Demo />,
root
)
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>