Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reset TabNavigator when user logs out (from other screen)

Here is my project file hierarchy

RootTabNavigator
    | AuthStackNavigator // I want to go back to this navigator
          | AuthoScreen
    | Welcome Screen
    | MainTabNavigator // I want to reset MainTabNavigator 
          | FeedStacknavigator
                   | Screen A
          | OtherStackNavigatorOne
                   | Screen E
          | OtherStackNavigatorTwo
                   | Screen D
          | MenuStackNavigator 
                   | Menuo <-I'm here and want to reset to 'MainTabNavigator' 
                             and go BACK to 'AuthScreen'
           | Screen B
                   | Screen C

Problem

The user is on Menuo Screen under MenuStackNavigator and MainTabNavigator.

If user doesn't have a token (when user logs out), user goes back to the Auth Screen.

But at the same time I want to RESET MainTabNavigator. You can unmount , perform NavigationActions.init() or whatever you can. I prefer NavigationActions.init()

I just want to set MainTabNavigator to its very first time.

Code

if there is no token, I go back to Auth Screen (This is working)

This code if the part of Menuo Screen

componentWillReceiveProps(nextProps) {
    if ( nextProps.token == undefined || _.isNil(nextProps.token) ) {
      const backAction = NavigationActions.back({
        key: null
      })
      nextProps.navigation.dispatch(backAction);
      ...

(Question) How can we reset MainTabNavigator including child StackNavigators?

MainTabNavigator.js

export default TabNavigator(
    {
        Feed: {
          screen: FeedStacknavigator,
        },
        OtherOne: {
          screen: OtherStackNavigatorOne,
        }
        ...
    }, {
        navigationOptions: ({navigation}) => ){
            header: null,
        tabBarIcon: ({focused}) => ...
        ...
    }

Possible Solution

I can maybe change MainTabNavigator from function to class and deal with resetting TabNavigator there. (I'm not sure).

This time, I need a concrete working example. I've been reading doc and applying to my app but I couldn't solve this.

Please let me know if anything is unclear.

UPDATE

const RootTabNavigator = TabNavigator ({
    Auth: {
      screen: AuthStackNavigator,
    },
    Welcome: {
      screen: WelcomeScreen,
    },
    Main: {
      screen: MainTabNavigator,
    },
  }, {
    navigationOptions: () => ({
     ...
  }
);

export default class RootNavigator extends React.Component {
  componentDidMount() {
    this._notificationSubscription = this._registerForPushNotifications();
  }
like image 240
merry-go-round Avatar asked Dec 21 '17 17:12

merry-go-round


People also ask

How do I reset stack in react navigation?

If you want every stack to reset when changing tabs you can remove the tabName === TAB_TO_RESET check. Learn all you need about React Navigation with our Master React Navigation v5 course!

How do I navigate to a Tabnavigator tab?

navigate({ routeName: 'Tab', action: NavigationActions. navigate({ routeName: 'Market', }), }), ], });

How do I go back to first screen in react native?

You can go back to an existing screen in the stack with navigation. navigate('RouteName') , and you can go back to the first screen in the stack with navigation. popToTop() .


2 Answers

This should work in most cases:

componentWillReceiveProps(nextProps) {
    if ( nextProps.token == undefined || _.isNil(nextProps.token) ) {

        let action = NavigationActions.reset({
            index: 0,
            key: null,
            actions: [
                NavigationActions.navigate({routeName: 'Auth'})
            ]
        });

        nextProps.navigation.dispatch(action);
    }
    ...
}

Or try by enhancing your navigator with custom action:

const changeAppNavigator = Navigator => {
   const router = Navigator.router;

   const defaultGetStateForAction = router.getStateForAction;

   router.getStateForAction = (action, state) => {
       if (state && action.type === "RESET_TO_AUTH") {
          let payLoad = {
              index: 0,
              key: null,
              actions: [NavigationActions.navigate({routeName: "AuthStackNavigator"})]
          };

          return defaultGetStateForAction(NavigationActions.reset(payLoad), state);
          // or this might work for you, not sure:
          // return defaultGetStateForAction(NavigationActions.init(), state)
       }
       return defaultGetStateForAction(action, state);
  };

  return Navigator;
};

const screens = { ... }

RootTabNavigator = changeAppNavigator(TabNavigator(screens, {
  initialRouteName: ...,
  ...
}));

Then in your Menuo Screen do:

componentWillReceiveProps(nextProps) {
    if ( nextProps.token == undefined || _.isNil(nextProps.token) ) {

        nextProps.navigation.dispatch({type: "RESET_TO_AUTH"});
    ...
like image 127
zarcode Avatar answered Oct 12 '22 12:10

zarcode


What you need is to initialize the navigator to the initial state. You can do that with NavigationActions.init(). You can learn more about Navigations Actions here.

You can do this by creating a Custom Navigation Action, read more about them here.

Here's some code that would do that for you:

// First get a hold of your navigator
const navigator = ...

// Get the original handler
const defaultGetStateForAction = navigator.router.getStateForAction

// Then hook into the router handler
navigator.router.getStateForAction = (action, state) => {

  if (action.type === 'MyCompleteReset') {
     // For your custom action, reset it all
     return defaultGetStateForAction(NavigationActions.init())
  }

  // Handle all other actions with the default handler
  return defaultGetStateForAction(action, state)
}

In order to trigger your Custom Navigation Action, you have to dispatch it as follows from within your React Component:

  this.props.navigation.dispatch({
      type: "MyCompleteReset",
      index: 0
    })
like image 20
idancali Avatar answered Oct 12 '22 13:10

idancali