React Native

React Navigation: do not go back repeatedly, use reset!

One thing we learnt from using React Navigation with React Native is how hard it is to go back properly in our nested stack navigators.

For example, let's take this navigator router: it has a ++code class="markup--code markup--p-code">StackNavigator++/code> as its root navigator and other nested navigators.

++pre>++code class="language-javascript">const RootNavigator = StackNavigator(
   {
     home: {
       screen: DrawerNavigator(
         {
           home: {
             screen: Pages.Home,
           },
         },
         {
           initialRouteName: 'home',
         }
       ),
       path: 'home',
     },
     authentication: {
       screen: StackNavigator({
         login: {
           screen: Pages.Login,
         },
         signin: {
           ...
         },
         signup: {
           ...
         },
       }),
     },
   },
   {
     initialRouteName: 'home',
   }
 );++/code>++/pre>

 

While you navigate in your application, at some point you might want to go back to the home page and clear all your navigation stack.

 

For example, if you are located on the login page, in your redux inspector, you would see:

++pre>++code>++code class="markup--code markup--pre-code">nav(pin)
 index(pin): 1
 ?routes(pin)
   ?0(pin)
     type(pin): "Navigation/NAVIGATE"
     routeName(pin): "home"
     ?routes(pin): [{?}, {?}, {?}]
     index(pin): 0
     key(pin): "id-1234567890123-3"
 ?1(pin)
   index(pin): 0
   ?routes(pin)
     ?0(pin)
       routeName(pin): "login"
       key(pin): "Init-id-1234567890123-5"
   key(pin): "id-1234567890123-6"
   routeName(pin): "authentication"++/code>++/pre>

 

The React Navigation reset method

In order to go back to the home page, you shouldn't use the method ++code class="markup--code markup--p-code">back++/code>of react-navigation repeatedly as it is suggested at the end of this thread for example. Instead, use ++code class="markup--code markup--p-code">reset++/code> with a ++code class="markup--code markup--p-code">key: null++/code> to ask react-navigation to reset the root navigator.

 

++table style="border-color: #ff0000;" border="1" cellpadding="5">++tbody>++tr>++td style="border-color: #ff0000; padding: 10px; border-width: 1px;">

Don't: this might be OK in dev environnement, but this will certainly make your bundled application crash in production environnement

++pre>++code>++code class="markup--code markup--pre-code">yield put(NavigationActions.back({ key: null }));
yield put(NavigationActions.back({ key: null }));
yield put(NavigationActions.back({ key: null }));
yield put(NavigationActions.back({ key: null }));++/code>
++/pre>++/td>++/tr>++/tbody>++/table>
++table style="width: 100%; border-color: #309e15;" border="1" cellpadding="5">++tbody>++tr>++td style="border-color: #429e10; padding: 10px;">

Do: properly reset the navigator

++pre>++code>++code class="markup--code markup--pre-code">yield put(
 NavigationActions.reset({
   key: null,
   index: 0,
   actions: [NavigationActions.navigate({ routeName: 'home' })],
 })
);++/code>++/pre>++/td>++/tr>++/tbody>++/table>

 

How does ++code class="markup--code markup--p-code">reset++/code> works ?

  • ++code class="markup--code markup--li-code">key++/code> refers to your nested navigator key you want to reset. As it is often complicated to get one navigator's key, the easiest way to use it is:
  • either leave it ++code class="markup--code markup--li-code">undefined++/code>: this way ++code class="markup--code markup--li-code">reset++/code> will apply to your current navigator:
  • either set it to ++code class="markup--code markup--li-code">null++/code>: this way ++code class="markup--code markup--li-code">reset++/code> will apply to your root navigator.


  • ++code class="markup--code markup--li-code">actions++/code> is an array of actions used to set the new navigation state.
  • ++code class="markup--code markup--li-code">index++/code> refers to the active screen in this new state.

 

For example?

++pre>++code>++code class="markup--code markup--pre-code">NavigationActions.reset({
 index: 1,
 actions: [
   NavigationActions.navigate({ routeName: 'home' }),
   NavigationActions.navigate({ routeName: 'settings' })
 ]
});++/code>++/pre>

? will replace your current navigator state by a state with the ++code class="markup--code markup--p-code">'settings'++/code> route on top of the ++code class="markup--code markup--p-code">'home'++/code> route; and the active route is the one which ++code class="markup--code markup--p-code">index++/code> is ++code class="markup--code markup--p-code">1++/code> i.e. the ++code class="markup--code markup--p-code">'settings'++/code> route.

 

Finally, in order to use properly React Navigation API, dispatch only one action at a time.

Développeur mobile ?

Rejoins nos équipes