React window unload event doesn't fire

10,353

Solution 1

You should bind this to the unload method or transform it to arrow function.

Binging way

constructor() {
    super();
    this.state = {
      //stuff
    };
    this.unload.bind(this);
  }

  componentDidMount() {
  window.addEventListener("beforeunload", this.unload);
}

componentWillUnmount() {
  window.removeEventListener("beforeunload", this.unload);
}

unload(e) {
  navigator.sendBeacon(`http://localhost:8080/window-closed/${this.props.username}`);
}

Arrow functions way:

  constructor() {
    super();
    this.state = {
      //stuff
    };
  }

  componentDidMount() {
  window.addEventListener("beforeunload", this.unload);
  }

  componentWillUnmount() {
    window.removeEventListener("beforeunload", this.unload);
  }

  unload = (e) => {
    navigator.sendBeacon(`http://localhost:8080/window-closed/${this.props.username}`);
  }

Remember to remove the eventlistener on componentWillUnmount (you are currently adding it again).

Solution 2

If you're using a functional component, you can try this:

 useEffect(() => {
    window.addEventListener("beforeunload", handleUnload);
    return () => {
      window.removeEventListener("beforeunload", handleUnload);
    };
  }, []);

  const handleUnload = (e) => {
    const message = "o/";
    (e || window.event).returnValue = message; //Gecko + IE
    return message;
  };


Solution 3

You may be able to use navigator.sendBeacon.

const UnloadBeacon = ({
  url,
  payload = () => {},
  children
}) => {
  const eventHandler = () => navigator.sendBeacon(url, payload())

  useEffect(() => {
    window.addEventListener('unload', eventHandler, true)
    return () => {
      window.removeEventListener('unload', eventHandler, true)
    }
  }, [])

  return children
}

full example here: https://gist.github.com/tmarshall/b5433a2c2acd5dbfc592bbc4dd4c519c

Share:
10,353
Sagi Rika
Author by

Sagi Rika

I am an experienced Full-Stack Engineer & problem solver with a great self-learning abiity and a lot of passion for innovation & design. I have experience in developing complex single page applications using technologies & frameworks such as React.JS, Node.JS, Redux, NoSQL, Redis, Docker, Cypress & more.

Updated on June 28, 2022

Comments

  • Sagi Rika
    Sagi Rika almost 2 years

    I need to use navigator.sendBeacon() on window unload in order to let my server know the client has closed his window. I have searched everywhere and it just doesn't work for me.

    For reference, the solution in this post didn't work either.

    I have an App component that wraps my entire project. I am trying to set the unload event on it's componentDidMount() lifecycle method, and it just won't fire.

    componentDidMount() {
      window.addEventListener("beforeunload", this.unload);
    }
    
    componentWillUnmount() {
      window.addEventListener("beforeunload", this.unload);
    }
    
    unload(e) {
      e.preventDefault();
      e.returnValue = 'test';
      navigator.sendBeacon(`http://localhost:8080/window-closed/${this.props.username}`);
      return 'test';
    }
    

    I expect the server to get the AJAX call, and the window to prompt the user 'test' before the window is closed. What actually happens is the window just closes as usual.

    NOTE: the return 'test' & e.returnValue = '' statements are purely for testing. I'm only interested in the AJAX request.

    Any help would be much appreciated.

  • Sagi Rika
    Sagi Rika about 5 years
    Im not sure how do you mean i should declare it in the constructor. Could you please show me an example of some sort?
  • mani9418
    mani9418 about 5 years
    Constructor (){ this.unload = this.unload.bind(this) And declare unload with arrow function
  • mani9418
    mani9418 about 5 years
    Also add event listeners are not recommend in react but for now you can go by the above approach to get things right (y)
  • Sagi Rika
    Sagi Rika about 5 years
    Thanks, used the arrow functions way and it suddenly started working like a charm.
  • AdamSulc
    AdamSulc almost 3 years
    Hey, I have similar issue currently, do you mind checking it out? stackoverflow.com/questions/67498997/…
  • Sachin Kumar
    Sachin Kumar over 2 years
    what if we have a prompt. like "Changes that you made may not be saved." even the user click on cancel button the "beforeunload" on window function called!