最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React window unload event doesn't fire - Stack Overflow

programmeradmin1浏览0评论

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.

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.

Share Improve this question edited Mar 28, 2019 at 17:58 Brian Tompsett - 汤莱恩 5,88372 gold badges61 silver badges133 bronze badges asked Mar 28, 2019 at 16:51 Sagi RikaSagi Rika 2,9793 gold badges16 silver badges35 bronze badges 3
  • Can you please provide with a codesandbox ? – Jibin Joseph Commented Mar 28, 2019 at 17:39
  • Try changing unload(e) { to unload = (e) => { – Gabriele Petrioli Commented Mar 28, 2019 at 18:09
  • Sadly, that didnt work :/ @GabrielePetrioli – Sagi Rika Commented Mar 28, 2019 at 18:18
Add a comment  | 

5 Answers 5

Reset to default 7

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;
  };


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

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).

Have you tried declaring upload function as a fat arrow function? Also declare it before componentDidMount. (for better readability) before passing it as a reference.

Also have you tried attaching listener in contructor ? And make surw to bind your function in constructor. For reference

Also destroy the listener at componentWillUnmount, instead of adding it. (useless) use reference to listener, to destroy. Which you will create in constructor.

Best of luck

I am unsure why beforeunload is not working, but as a workaround, you may consider using the hashchange event.

componentDidMount() {
    window.addEventListener("hashchange", this.doSomething, false);
}

componentWillUnmount() {
    window.removeEventListener("hashchange", this.doSomething, false);
}
发布评论

评论列表(0)

  1. 暂无评论