componentWillUnmount() not being called when refreshing the current page

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>

Leave a Comment