2020年12月31日星期四

React Router v5.2 - Blocking route change with createBrowserHistory and history.block

My app has two pages: Step1 and Step2. Step1 has a checkbox that blocks navigation if it is checked and a Next button that navigates to Step2 when clicked. Step2 has a Previous button that navigates back to Step1 when clicked.

Link to demo

As per this tutorial, I'm using the block method of the createBrowserHistory object to block route changes if the checkbox in Step1 is checked:

const unblock = useRef();      useEffect(() => {      unblock.current = history.block((tx) => {        if (block.current.checked) {          const promptMessage = "Are you sure you want to leave?";            if (window.confirm(promptMessage)) {            unblock.current();            tx.retry();          }        } else {          console.log("tfgx");          unblock.current();          tx.retry();        }      });    }, []);  

I also had to set the history prop in the low-level <Router> (not <BrowserRouter>) to the createBrowserHistory object, like so:

<Router history={createBrowserHistory()}>  ...  </Router>  

But this prevents the routes from being rendered properly. I think this may have something to do with <Switch> not being able to read the location object properly. If I use <BrowserRouter>, the location object looks like this: {pathname: "/step1", ... key: "7sd45"}. But when I use <Router={createBrowserHistory()}>, the location object looks like this {action: "PUSH", location: {pathname: "/step1", ... key: "7sd45"}}. (I'm also getting the warning You cannot change <Router history>.)

My desired result is to block navigation if the 'Block navigation' checkbox is checked and unblock it otherwise. If the location changes when navigation is unblocked, I would like the corresponding route to be rendered correctly.

The section on createBrowserHisory in the React Router v5 docs is sparse and there aren't many examples that make use of it, so I'd be grateful if someone could shed some light on this.


EDIT: Passing location.location to <Switch> seems to fix it (Updated demo). But if I call useLocation inside Step1 and print the result (line 17-18), I get {pathname: "/step1", ... key: "7sd45"} and not {action: "PUSH", location: {pathname: "/step1", ... key: "7sd45"}}. Why is this?

Also, if the user attempts to go to another location when navigation is blocked, my custom prompt appears as expected ("Are you sure you want to leave" with "OK" and "Cancel" buttons). However, if they dismiss this by clicking Cancel, then the browser's own dialog box appears -

In Chrome:

enter image description here

In Firefox:

enter image description here

Is it possible to suppress the browser prompt after my prompt has been dismissed?

https://stackoverflow.com/questions/65526447/react-router-v5-2-blocking-route-change-with-createbrowserhistory-and-history January 01, 2021 at 08:10AM

没有评论:

发表评论