Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent the unmount in React Components?

I'm trying to implement a feature in my app where when the user tries to navigate away from an un-submitted form, they're given an confirm that asks them if they're sure they want to leave before saving their changes.

The componentWillUnmount method seems like perfect candidate for this because it will fire for all the various ways that a user may abandon the form (changes a parent component state that causes it to disappear, navigates to a different route, etc...). However... I have no way to prevent the unmount when the confirm returns false.

Any suggestions on how I can go about implementing this?

like image 218
Joshua Navarro Ruíz Avatar asked May 07 '17 05:05

Joshua Navarro Ruíz


2 Answers

Using react-router you can easily prevent route change(which will prevent component unmount) by using Prompt.

import { Prompt } from 'react-router';

const BlockingComponent = ({ isBlocking }) => (
  <div>
    <Prompt
      when={isBlocking}
      message={location =>
        `Are you sure you want to go to ${location.pathname}`
      }
    />
    {/* Rest of the JSX of your component */}
  </div>
);

Here isBlocking should be a bool indicating whether a blocking prompt should be shown or not. You can find a complete demo on react-router website

This method will work for BrowserRouter and HashRouter, but if you are using MemoryRouter, you need to create your Router as shown below then use Prompt in your components:

<MemoryRouter
  getUserConfirmation={(message, callback) => {
    callback(window.confirm(message));
  }}
>
  {/* Your App */}
</MemoryRouter>

You need to manually pass the getUserConfirmation prop which is a function.
You can modify this function as you like in any Router(Browser, Memory or Hash) to create your custom confirmation dialog(eg. a modal) instead of using the browser's default confirm.

like image 52
Vaibhav Vishal Avatar answered Oct 19 '22 17:10

Vaibhav Vishal


This is best handled via react-router: setRouteLeaveHook.

componentWillMount() {
    this.unregisterLeaveHook = props.router.setRouteLeaveHook(props.route, this.routerWillLeave.bind(this));
}

routerWillLeave(nextLocation) {
  return false;        
}

And when component is unmounted, unregister the leave hook:

componentWillUnmount() {
    this.unregisterLeaveHook();
}
like image 11
vijayst Avatar answered Oct 19 '22 17:10

vijayst