Javascript reactjs 事件监听器 beforeunload 添加但未删除

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39094138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 22:11:41  来源:igfitidea点击:

reactjs event listener beforeunload added but not removed

javascriptreactjsaddeventlistenerevent-listener

提问by gamer

I have a react component like :

我有一个反应组件,如:

import React, { PropTypes, Component } from 'react'


class MyComponent extends Component {

    componentDidMount() {
       window.addEventListener("beforeunload", function (event) {
            console.log("hellooww")
            event.returnValue = "Hellooww"
        })
    }

    componentWillUnmount() {
        window.removeEventListener("beforeunload", function (event) {
            console.log("hellooww")
            event.returnValue = "Hellooww"
        })
    }

    render() {

        return (
            <div>
                Some content
            </div>
        )
    }

}

export default MyComponent

Here event lister is added to the component. When I refresh the page it gives me pop up asking to leave the page.

这里事件列表器被添加到组件中。当我刷新页面时,它让我弹出要求离开页面。

But when I go to another page and do refresh it again shows the same pop-up.

但是当我转到另一个页面并再次刷新时,它会显示相同的弹出窗口。

I am removing the eventListenerfrom the component on componentWillUnmount. Then why it is not being removed?

我正在eventListener从组件中删除componentWillUnmount。那为什么不删除呢?

How can I remove the beforeunloadevent on other pages?

如何删除beforeunload其他页面上的事件?

回答by Ori Drori

The removeEventListenershould get the reference to the same callback that was assigned in addEventListener. Recreating the function won't do. The solution is to create the callback elsewhere (onUnloadin this example), and pass it as reference to both addEventListenerand removeEventListener:

removeEventListener应该得到的引用到在分配相同的回调addEventListener。重新创建该函数是行不通的。解决方案是在别处创建回调(onUnload在本例中),并将其作为对addEventListener和 的引用传递removeEventListener

import React, { PropTypes, Component } from 'react';


class MyComponent extends Component {
    onUnload = e => { // the method that will be used for both add and remove event
       e.preventDefault();
       e.returnValue = '';
    }

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

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

    render() {
        return (
            <div>
                Some content
            </div>
        );
    }

}

export default MyComponent

React hooks

反应钩子

You can abstract the beforeunloadevent handling to a custom hook with the useRef, and useEffecthooks.

您可以beforeunload使用useRef, 和useEffect挂钩将事件处理抽象为自定义挂钩。

The custom hook useUnloadreceives a function (fn) and assigns it to the current ref. It calls useEffect, and sets the event handler, and returns a cleanup function to remove the event handler, when the component is removed.

自定义钩子useUnload接收一个函数 ( fn) 并将其分配给当前的 ref。useEffect当组件被移除时,它调用,并设置事件处理程序,并返回一个清除函数来移除事件处理程序。

import { useRef, useEffect } from 'react';

const useUnload = fn => {
  const cb = useRef(fn);

  useEffect(() => {
    const onUnload = cb.current;

    window.addEventListener("beforeunload", onUnload);

    return () => window.removeEventListener("beforeunload", onUnload);
  }, [cb]);
};

export default useUnload;

Usage:

用法:

const MyComponent = () => {
  useUnload(e => {
    e.preventDefault();
    e.returnValue = '';
  });

  return (
    <div>
      Some content
    </div>
  );
};

回答by Michael

Ori's solution didn't work for me. I had to do this to make it work... (Thank you docs)

Ori 的解决方案对我不起作用。我必须这样做才能使其正常工作......(谢谢文档)

  componentDidMount() {
    window.addEventListener('beforeunload', this.handleLeavePage);
  }

  componentWillUnmount() {
    window.removeEventListener('beforeunload', this.handleLeavePage);
  }

  handleLeavePage(e) {
    const confirmationMessage = 'Some message';
    e.returnValue = confirmationMessage;     // Gecko, Trident, Chrome 34+
    return confirmationMessage;              // Gecko, WebKit, Chrome <34
  }