首页 > 解决方案 > beforeunload 仅适用于页面刷新,不适用于页面离开

问题描述

我正在使用react-admin框架(3.2)并且我试图beforeunload在用户从Edit form视图中导航时触发事件。可以说我的路径名是"feed/123". 当 url 以任何方式更改时(用户正在离开编辑表单),beforeunload应该触发。到目前为止,我已经尝试过这段代码:

const FeedEdit = props => {
    const alertUser = (e) =>
    {
        e.preventDefault();
        e.returnValue = '';
        console.log('fired'); //console.log is present on F5, not when leaving the page
    }

    useEffect(() =>
    {
        window.addEventListener('beforeunload', alertUser);
        return () => { window.removeEventListener('beforeunload', alertUser); };
    }, [])

    return <>
        <PageTitle type="edit" {...props} />
        <Edit {...props}>
          {/* other components */}
        </Edit>
    </>
};

但是,这只beforeunload在刷新 url 时触发事件。任何想法如何在离开表单时触发事件?

先感谢您

标签: javascriptreactjsreact-admin

解决方案


是的,没错,因为当您离开页面时会触发卸载,但是当您替换 url 时,您仍然在同一个页面中具有不同的内容......

您可以通过添加一个新钩子来跟踪组件包装器中的位置更改来做到这一点:

  const location = useLocation();

  useEffect(() => {
    console.log('Location changed', location);
  }, [location]);

注意:你有很多选项可以帮助你反应路由器,你也可以构建一个自定义钩子来在你想要的任何地方重复使用跟踪代码......(如果你想为特定的路由组件处理它)

==================

更新 1

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);
    window.addEventListener("unload", onUnload);

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

export default useUnload;

这是一个用于处理卸载页面的自定义钩子,我们可以通过在需要的组件中调用它来使用它,如下所示:

  // When Un-load event is trigger then trigger dis-counect and remove local track
  const unload = useCallback(() => {
....
  }, []);

  // Add event lisiner to trigger before unload
  useUnload(unload);

==================

更新 2

对于历史监听器,您可以使用history.listen,例如:

  useEffect(() => {
    history.listen((loc, action) => {
      if(action === "POP"){// POP or PUSH
        window.location.reload();
      }
    });
  }, []);

推荐阅读