反应窗口卸载事件不会触发

时间:2019-03-28 16:51:49

标签: javascript ajax reactjs dom-events

我需要在窗口卸载时使用navigator.sendBeacon(),以便让我的服务器知道客户端已关闭其窗口。我到处搜索了,但对我来说不起作用。

作为参考,this post中的解决方案也不起作用。

我有一个包裹整个项目的App组件。我正在尝试在其componentDidMount()生命周期方法上设置unload事件,但它不会触发。

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

我希望服务器获得AJAX调用,并且该窗口在关闭窗口之前提示用户“测试”。实际发生的是窗口照常关闭。

注意:return 'test'e.returnValue = ''语句仅用于测试。我只对AJAX请求感兴趣。

任何帮助将不胜感激。

5 个答案:

答案 0 :(得分:1)

您应该将此绑定到unload方法或将其转换为箭头功能。

单打方式

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

箭头功能方式:

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

请记住要删除componentWillUnmount上的事件监听器(您当前正在再次添加它)。

答案 1 :(得分:1)

您也许可以使用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
}

完整示例:https://gist.github.com/tmarshall/b5433a2c2acd5dbfc592bbc4dd4c519c

答案 2 :(得分:0)

您是否尝试过将上传功能声明为粗箭头功能?还要在componentDidMount之前声明它。 (以提高可读性),然后再将其作为参考。

您还尝试在构造器中附加侦听器吗?并浏览绑定到构造函数中的函数。供参考

也销毁位于componentWillUnmount的侦听器,而不是添加它。 (无用)使用对侦听器的引用来销毁。您将在构造函数中创建的对象。

祝你好运

答案 3 :(得分:0)

如果您使用的是功能组件,则可以尝试以下操作:

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


答案 4 :(得分:-1)

我不确定beforeunload为何不起作用,但是作为一种解决方法,您可以考虑使用hashchange事件。

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

componentWillUnmount() {
    window.removeEventListener("hashchange", this.doSomething, false);
}