6

Im try to understand how to reset in nested stack this my code

    const AuthStack = createStackNavigator(
      {
        Welcome,
        Login,
        Register,
        ConfirmationCode,
      },
      {
        initialRouteName: 'Welcome',
        headerMode: 'none',
        lazy: true,
        transitionConfig,
        defaultNavigationOptions: {
          gesturesEnabled: false,
        },
      }
    )

    const AppStack = createStackNavigator(
      {
        TabStack,
        SearchResult,
        BusinessDetail,
        BusinessMap,
        MakeAppointment,
        TermsAndConditions
      },
      {
        initialRouteName: 'TabStack',
        headerMode: 'none',
        lazy: true,
        transitionConfig,
        defaultNavigationOptions: {
          gesturesEnabled: false,
        },
      }
    )

    let MainStack = createSwitchNavigator(
      {
        AuthLoading,
        Auth: AuthStack,
        App: AppStack,
      },
      {
        initialRouteName: 'AuthLoading',
        headerMode: 'none',
        lazy: true,

        defaultNavigationOptions: {
          gesturesEnabled: false,
        },
      }
    )

TabStack

    import React from 'react';

    import { createBottomTabNavigator, createAppContainer } from 'react-navigation';
    import {
        Search,
        MyFavourites,
        MyAppointments,
        UserProfile
    } from '../screens'
    import Icon from 'react-native-vector-icons/Feather';
    import Colors from '../utils/Colors'
    let TabStack = createBottomTabNavigator(
      {
        Search,
         MyFavourites,
         MyAppointments,
         UserProfile,
      },
        initialRouteName: 'ScreenTab1',
        tabBarOptions: {
          activeTintColor: Colors.pink,
          inactiveTintColor: Colors.black,
          showLabel: false,
          style: {
            backgroundColor: 'white'
          }
        },
      }
    )
    export default createAppContainer(TabStack);

I want to understand how to make reset for example:

    reset from UserProfile to TabStack (in AppStack) to AuthStack

I tried to do from it this way

const resetAction = StackActions.reset({
        index: 0,
        actions: [NavigationActions.navigate({ routeName: 'AuthStack' })],
    });
    this.props.navigation.dispatch(resetAction);

or this way

const resetAction = StackActions.reset({
        index: 0,
        key: null,
        actions: [NavigationActions.navigate({ routeName: 'AuthStack' })],
    });
    this.props.navigation.dispatch(resetAction);

but i got the error

there is no route defined for AuthStack

I checked in issues in stackoverflow but the answers there not works for me,always show me the same error I wrote above.

Fatih Aktaş
  • 1,446
  • 13
  • 25
Manspof
  • 598
  • 26
  • 81
  • 173
  • 1
    Possible duplicate of [React Native navigating between Nested StackNavigator](https://stackoverflow.com/questions/54704752/react-native-navigating-between-nested-stacknavigator) – Jaydeep Galani Feb 19 '19 at 03:31
  • @JaydeepGalani I tried this solution, not working, it show the same error. – Manspof Feb 19 '19 at 05:28
  • Check your route name, it should be `Auth` instead of `AuthStack` as your declaration :) And reset with key null will work cause it'll reset the root nav. – tuan.tran Feb 23 '19 at 09:07
  • I did as you can see here, same error https://pastebin.com/hvJ7Mp7b – Manspof Feb 23 '19 at 16:25

3 Answers3

4

Your resetAction is unsuccessful because you are dispatching it on TabStack (because you are calling this.props.navigation.dispatch on UserProfile, if I get you correctly). You need to dispatch the resetAction to your MainStack instead. This thread here suggested some ways that you can achieve this. And also, here is my preferred solution, because i don't have to pass props around navigators or calls multiple nested actions with this.

  1. Create a navigationService.js with the following contents (to keep your top level navigator as a reference)
import { NavigationActions, StackActions } from 'react-navigation';

let _navigator;

function setTopLevelNavigator(navigatorRef) {
  _navigator = navigatorRef;
}

function navigateMainNavigator(routeName, params) {
  _navigator.dispatch(
    NavigationActions.navigate({
      routeName,
      params,
    }),
  );
}

// add other navigation functions that you need and export them

export default {
  setTopLevelNavigator,
  navigateMainNavigator,
};
  1. On your App.js or any other file you render your MainStack, do this to set the reference
import NavigationService from './navigationService';

...

render() {
  return (

    ...
    <MainStack
      ref={navigatorRef => {
        NavigationService.setTopLevelNavigator(navigatorRef);
      }}
    />
    ...

  )
}
  1. And wherever when you want to reset to your AuthStack (or any other stack in your MainStack), just import NavigationService and call
NavigationService.navigateAndReset('Auth', {...yourParamsIfAny});
// 'Auth' because you named it that way in your 'MainStack'

===========================================================================

Edited

Previous solution, in navigationService.js, is for StackNavigator as the MainStack

function navigateAndReset(routeName, params) {
  _navigator.dispatch(
    StackActions.reset({
      index: 0,
      actions: [
        NavigationActions.navigate({
          routeName,
          params,
        }),
      ],
    })
  );
}
wicky
  • 948
  • 6
  • 13
  • hey wicky, sounds like great way to do that! Im using with mobx so I did it in my store, I copy part of my code here, you can see https://pastebin.com/KtnMAXYy I also printed the ref to see what's it include and see all his properties. but I still got same error.. maybe I miss something.. – Manspof Feb 26 '19 at 07:02
  • Hey Adir, I am not familiar with mobx. But try doing a `conosle.log(this.main_navigation_ref)` on your `resetMainStack` function, and check if you're on the correct navigator. Try looking for the navigator's routes, [this image](https://imgur.com/a/GTXUDYg) might help – wicky Feb 26 '19 at 07:51
  • you can see the console.log here https://imgur.com/a/tWhfMHA it show me the mainStack – Manspof Feb 26 '19 at 09:35
  • Ahh, I just realise your `MainStack` is actually a `SwitchNavigator`. In that case, you dont need the `StackActions.reset` action. Just the `NavigationActions.navigate` will do. I have updated my answer above – wicky Feb 26 '19 at 09:52
  • exactly what I need!!!! what the difference between stack actions.reset to NavigationActions? – Manspof Feb 26 '19 at 09:56
  • Gald it helps. `StackActions.reset` (with `index: 0`) is to reset your `StackNavigator`'s stack, so that when you push a new screen using `NavigationActions.navigate` to it, the new screen will be the first screen on the `StackNavigator`. Without `StackActions.reset`, it will push the new screen on top of the stack, which you can still go back to the previous screen using the `back button` or `swipe left`. Since your `MainStack` is a `SwitchNavigator` but not a `StackNavigator`, you dont need to reset the stack. – wicky Feb 26 '19 at 10:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/189062/discussion-between-adir-zoari-and-wicky). – Manspof Feb 26 '19 at 10:16
1

Try by setting it to AppStack, because anyhow it is going to redirect to GeneralStack as you have it as initialRouteName inside AppStack

const resetAction = StackActions.reset({
      index: 0,
      key: null,
      actions: [NavigationActions.navigate({ routeName: 'App' })],
    });
    this.props.navigation.dispatch(resetAction);
Ravi
  • 34,851
  • 21
  • 122
  • 183
  • What do u mean? I want to reset from userProfile of tabstack to screenA of authstack.. how to do that? – Manspof Feb 21 '19 at 06:57
  • But in question you are trying to reset it to `GeneratStack` instead of `AuthStack` – Ravi Feb 21 '19 at 07:03
  • I try to do some resets, the last one i ask you is to implement logout.. any idea? – Manspof Feb 21 '19 at 07:19
  • In that case you can directly reset it to `Auth` – Ravi Feb 21 '19 at 07:25
  • I tried to reset from UserProfile of tabStack to screenA of AuthStack with this code https://pastebin.com/hvJ7Mp7b . I get the same error "error:error:there is no route defined for key Auth. must be one of 'TabStack,...." – Manspof Feb 21 '19 at 08:12
  • @ I edit my post with real names to make it easier understand. check again – Adir Zoari 9 mins ago Delete – Manspof Feb 21 '19 at 08:28
  • @RaviRupareliya, In my case MainNav is StackNav, Also I have a switchNav within it, then a StackNav within the switchNav. I want to rest the inner stackNav in some situations but it fails. it seems the outer stack going to reset and because I'm passing one of the inner StackNav routeName it can not find that on outer stackNav. I have a NavigationService util file just like you post in your answer. have you any idea how can I fix it? – Saeed Zhiany Aug 12 '19 at 15:05
0

You can do the following, to reset to authStack,

create a reset actions as following,

const resetAction = StackActions.reset({
  index: 0,
  actions: [NavigationActions.navigate({ routeName: "AuthStack" })],
  key: null
});
this.props.navigation.dispatch(resetAction);

and also add the AuthStack into appStack, or the stack from which you are calling the above code.

For example if your calling this from your appstack, add the following line as a route within your app stack

  const AppStack = createStackNavigator(
  {
    TabStack,
    SearchResult,
    BusinessDetail,
    BusinessMap,
    MakeAppointment,
    TermsAndConditions,
    AuthStack <---Insert THIS
  },

This works for me when using to signout.

Naveed Sheriffdeen
  • 940
  • 6
  • 18
  • 37
  • I know this kind of way but I dont think this right way.. becauae if i want to reset in more complex stacks so i need always declare it in same level of stack... – Manspof Feb 22 '19 at 10:13