删除 beforeunload 事件在 React 中不起作用

问题描述 投票:0回答:1

下面的代码片段假设添加和删除事件监听器

handleBeforeUnload
。在检查浏览器控制台时,我看到打印了“inside else”,但是加载页面仍然会引发警报。

有什么想法为什么事件侦听器可能不会被删除吗?

useEffect(() => {
    const handleBeforeUnload = (e) => {
      e.preventDefault();
      const message =
        'Are you sure you want to leave? All provided data will be lost.';
      e.returnValue = message;
      return message;
    };

    if (condition1 && condition2) {
      console.log('inside if');
      window.addEventListener('beforeunload', handleBeforeUnload);
    } else {
      console.log('inside else');
      window.removeEventListener('beforeunload', handleBeforeUnload);
    }
  }, [stateVariable1, stateVariable2, stateVariable3]);

此外,除了使用

beforeunload
事件之外,还有其他方法可以检测重新加载吗?由于
returnValue
属性已被弃用,默认消息确实没有帮助。如何检测和创建自定义警报消息?

即使控制台打印 else 语句,我仍然看到弹出窗口,这意味着理想情况下应该删除事件侦听器。

reactjs event-handling dom-events simple-html-dom onbeforeunload
1个回答
1
投票

这是因为事件监听函数

handleBeforeUnload
是在effect内部定义的。因此,当效果再次运行以将其删除时,会重新创建
handleBeforeUnload
函数,这与效果运行到 register 事件侦听器时使用的函数并不等效。

要解决此问题,您需要从效果中返回一个 cleanup 函数。返回的清理函数将在 next 效果执行运行之前由 React 执行。由于该闭包引用了用于从该效果执行中注册它的确切(指相同)

handleBeforeUnload
,因此它将起作用。

当条件评估为 false 时,先前注册的处理程序的清理函数将被删除,并且不会注册新的处理程序,因为它受到该条件的保护。

useEffect(() => {
    const handleBeforeUnload = (e) => {
      e.preventDefault();
      const message =
        'Are you sure you want to leave? All provided data will be lost.';
      e.returnValue = message;
      return message;
    };

    if (condition1 && condition2) {
      window.addEventListener('beforeunload', handleBeforeUnload);
    }

    return () => {
        window.removeEventListener('beforeunload', handleBeforeUnload);
    }

  }, [stateVariable1, stateVariable2, stateVariable3]);

此外,是否有其他方法可以检测重新加载 比使用 beforeunload 事件?

不,没有。这是有目的的限制,因为阻止用户离开必须在网络标准中严格控制,因为它可能会被滥用。

© www.soinside.com 2019 - 2024. All rights reserved.