javascriptreactjsreact-router-dompage-transition

React router dom v6 prevent transition without <Prompt>


I've learned that with react-router-dom v5 it was possible to use the <Prompt> component in order to ask the user before a page transition happens, so that the user can prevent it.

Now, for the time being, they removed it from v6 (planning to have a robust implementation "sometime later"). Instead, they recommended to implement an equivalent component by yourself ... which I would like to do now.

But: I've found no way to actually prevent the page transition in react-router-dom v6. Does anyone know anything about it?


Solution

  • You can but it requires using a custom history object and HistoryRouter. For this history@5 needs to be a package dependency.

    1. Import version 5 of history.

      npm i -S history@5
      
    2. Create and export a custom history object.

      import { createBrowserHistory } from 'history';
      
      export default createBrowserHistory();
      
    3. Import and render a HistoryRouter and pass history as a prop.

      ...
      import { unstable_HistoryRouter as Router } from "react-router-dom";
      import history from './history';
      ...
      
      <Router history={history}>
        <App />
      </Router>
      
    4. Follow the docs for blocking transitions.

      // Block navigation and register a callback that
      // fires when a navigation attempt is blocked.
      let unblock = history.block((tx) => {
        // Navigation was blocked! Let's show a confirmation dialog
        // so the user can decide if they actually want to navigate
        // away and discard changes they've made in the current page.
        let url = tx.location.pathname;
        if (window.confirm(`Are you sure you want to go to ${url}?`)) {
          // Unblock the navigation.
          unblock();
      
          // Retry the transition.
          tx.retry();
        }
      });
      

    Demo:

    Edit agitated-blackwell-dpl9b3