reactjs event listener beforeunload added but not removed

前端 未结 2 478
说谎
说谎 2020-12-02 14:16

I have a react component like :

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


class MyComponent extends Component {

    componentDidMount() {
             


        
相关标签:
2条回答
  • 2020-12-02 14:45

    The removeEventListener should 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 (onUnload in this example), and pass it as reference to both addEventListener and 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 beforeunload event handling to a custom hook with the useRef, and useEffect hooks.

    The custom hook useUnload receives 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.

    import { useRef, useEffect } from 'react';
    
    const useUnload = fn => {
      const cb = useRef(fn); // init with fn, so that type checkers won't assume that current might be undefined
    
      useEffect(() => {
        cb.current = fn;
      }, [fn]);
    
      useEffect(() => {
        const onUnload = cb.current;
    
        window.addEventListener("beforeunload", onUnload);
    
        return () => window.removeEventListener("beforeunload", onUnload);
      }, []);
    };
    
    export default useUnload;
    

    Usage:

    const MyComponent = () => {
      useUnload(e => {
        e.preventDefault();
        e.returnValue = '';
      });
    
      return (
        <div>
          Some content
        </div>
      );
    };
    
    0 讨论(0)
  • 2020-12-02 14:54

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

      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
      }
    
    0 讨论(0)
提交回复
热议问题