Next.js에서 beforeunload 이벤트 처리

곤란한 일



Next.js에서 관리 화면 등의 구현을 할 때는 beforeunload 사용하고 싶을 때 있어요 ~
단지 Next.js의 <Link> 태그나 Router.push() 로 페이지 천이를 해도 beforeunload 이벤트는 발행되지 않습니다.
(SPA에서는 풀 페이지 리로드가 아닌 View간에만 페이지 천이를 실시하고 있기 때문에 당연)



참조 : Browser Back Button does not trigger window.onbeforeunload · Issue #2694 · vercel/next.js

여기서 수수하게 막혔다. . .

해결책



Next.js의 <Link> 태그나 Router.push() 대신에 <a> 태그나 window.location.href를 사용한다.
이것이 현재의 해결책이 될 것 같습니다.
(SPA로서의 페이지 천이는 포기한다)

그건 그렇고



실제로 쓰면 이런 느낌이 듭니다.
import React, { useEffect } from 'react';
import { Button } from 'antd';

// 共通の関数をイベント登録、解除時に渡す必要あり
const showAlert = (event: any) => {
  event.preventDefault();
  event.returnValue = '';
};

type Props = {
  handleClick: (event: any) => void;
};

const Main: React.FC<Props> = () => {
  const handleRemoveClick = () =>
    // ページ離脱前の確認(イベント解除)
    window.removeEventListener('beforeunload', showAlert, false);

  const handleLinkBtnClick = () => {
    window.location.href = '/';
  };

  return (
    <>
      <Button type="primary" htmlType="submit" onClick={handleRemoveClick}>
        イベント解除
      </Button>
      <a href="/">リンク1</a>
      <Button type="primary" htmlType="submit" onClick={handleLinkBtnClick}>
        リンク2
      </Button>
    </>
  );
};

const Index = () => {
  useEffect(() => {
    // ページ離脱前の確認(イベント登録)
    if (window) window.addEventListener('beforeunload', showAlert, false);
  }, []);

  return (
    <>
      <h1>beforeUnload</h1>
      <Main handleClick={showAlert} />
    </>
  );
};

export default Index;

  return (
    <Button type="primary" htmlType="submit" onClick={handleClick}>
      イベント解除
    </Button>
  );
};

const Index = () => {
  useEffect(() => {
    // ページ離脱前の確認(イベント登録)
    if (window) window.addEventListener('beforeunload', showAlert, false);
  }, []);

  return (
    <>
      <h1>beforeUnload</h1>
      <Main handleClick={showAlert} />
    </>
  );
};

export default Index;


마지막으로



이상, 「Next.js로 beforeunload 이벤트를 다루는」이었습니다.
Next.js 유능하고 일단 next/router나 ../link 사용하면 좋다~적인 달콤한 생각에 숨어 있는 함정이었습니다.
이것이 최선의 방법인지는 모르겠지만 혼잡한 분은 시도하십시오.
더 좋은 방법이 있다면 코멘트를 기다리고 있습니다! !

좋은 웹페이지 즐겨찾기