2

I'm trying to achieve the following with Gatsby

  1. The user is on a form page, if they hit the browser back button, a pop up would appear, asking if they want to leave.
  2. If the user selects ok, then it would go back.
  3. If the user selects cancel, then it would stay on this page

I was able to "almost" make it happen by doing the following

useEffect(() => {
    const confirmExit = e => {
      const leaveThisPage = window.confirm("Would you like to leave this page?")
      if (!leaveThisPage) {
        window.history.forward()
      }
    }
    window.addEventListener("popstate", confirmExit)
    return () => {
      window.removeEventListener("popstate", confirmExit)
    }
  }, [])

There is one issue, if the user selects cancel, then the browser would go to the previous page. Then window.history.forward() would fire and sends them back.

I noticed that popstate event cannot be cancelled, so e.preventDefault() won't work.

Note: I also tried to test with window.onbeforeunload, but it only triggers if I close to window, or if my previous is from outside my app. Is there a work around for my issue?

Phantom
  • 423
  • 1
  • 5
  • 13

1 Answers1

1

Gatsby is using @reach/router under the hood, which doesn't support intercepting and preventing navigation (emphasis mine):

No history blocking. I found that the only use-case I had was preventing the user from navigating away from a half-filled out form. Not only is it pretty easy to just save the form state to session storage and bring it back when they return, but history blocking doesn’t happen when you navigate away from the app (say to another domain). This kept me from actually using history blocking and always opting to save the form state to session storage. (Source)

I second the recommendation for saving the form state using localStorage.

coreyward
  • 77,547
  • 20
  • 137
  • 166