Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to actually use reset from a nested navigator? #1949

Closed
ghost opened this issue Jun 20, 2017 · 16 comments
Closed

How to actually use reset from a nested navigator? #1949

ghost opened this issue Jun 20, 2017 · 16 comments
Labels

Comments

@ghost
Copy link

ghost commented Jun 20, 2017

Months later, still can't figure out how to use reset() properly.

Looking through all the open and closed issues regarding the usage of reset() gives no clear direction on how to actually use it properly. A lot of people have stacks on stacks on stacks and it just doesn't work.

For example, my app is a TabNavigator, and one of my tabs is a DrawerNavigator, and each item in the drawer is a StackNavigator, so if I'm inside a StackNavigator and want to reset() to a different tab, I'm SOL... I get your standard "the route doesn't exist, use one that's available inside the StackNavigator you're currently in" message.

My Structure

Tab Navigator
– SplashTab (StackNavigator)
– RegisterTab (StackNavigator)
– AppTab (DrawerNavigator)
    – Settings Screen (StackNavigator)
        – Profile Screen // sign out button that reset() to RegisterTab

My Reset

const resetAction = NavigationActions.reset({
    index: 0,
    actions: [
        NavigationActions.navigate({routeName: 'RegisterTab'})
    ]
});
this.props.navigation.dispatch(resetAction); // Triggered by a button press
@iRoachie
Copy link

iRoachie commented Jun 21, 2017

You can pass down the root navigation object as a prop on your child routes. Instead of using component name in your route config, you can render a component.

Stack Navigator
- Login
- Password
- Main(Drawer Navigator)
   - Profile Screen // signout button
 Main: {
      screen: ({ navigation }) =>
        <Main screenProps={{ rootNavigation: navigation }} />,
    }

Account:

onPress={() => {
            props.rootNavigation.dispatch(
              NavigationActions.reset({
                index: 0,
                actions: [NavigationActions.navigate({ routeName: 'Login' })]
              })
            )
}}

@valetarton
Copy link

That is how I currently achieve that need.

@jsoendermann
Copy link

@iRoachie Do you have any advice on how I can make this work with Redux? If I use your method, the nested Navigator isn't connected to my redux store anymore.
Thanks!

@iRoachie
Copy link

@jsoendermann Not sure mate, haven't used react-navigation with redux as yet. Passing down props currently works for my needs

@jsoendermann
Copy link

I see, thanks anyway.

@nhohb07
Copy link

nhohb07 commented Jun 22, 2017

@iRoachie work fine, thanks

@augustoabreu
Copy link

const resetAction = NavigationActions.reset({
    index: 0,
    key: null,
    actions: [
        NavigationActions.navigate({routeName: 'RegisterTab'})
    ]
});
this.props.navigation.dispatch(resetAction); // Triggered by a button press

@ghost
Copy link
Author

ghost commented Jun 22, 2017

I've made some progress with @iRoachie's approach; however, I seem to be passing down the "AuthTab" navigator into the "AppTab" at the TabRoutes configuration level, which I'm debugging....

@augustoabreu Your solution is what I see in a lot of places, passing key as null; however, this does not work with nested navigators.

@ghost
Copy link
Author

ghost commented Jun 22, 2017

Here's how I'm passing my rootNavigation to the AppTab, which appears to be the navigator for the AuthTab when I try using it.

TabNavigation({
    SplashTab: {
        screen: SplashScreen,
        navigationOptions: { title: 'Splash' }
    },
    IntroTab: {
        screen: IntroScreen,
        navigationOptions: { title: 'Intro'}
    },
    AuthTab: {
        screen: AuthNavigator,
        navigationOptions: { title: 'Auth' }
    },
    AppTab: {
        screen: ({ navigation }) => <AppDrawer screenProps={{ rootNavigation: navigation }} />,
        navigationOptions: { title: 'App' }
    }
}, {
    initialRouteName: 'SplashTab',
    backBehavior: 'none',
    swipeEnabled: false,
    tabBarPosition: 'bottom',
    lazy: true,
    animationEnabled: true,
    navigationOptions: {
        tabBarVisible: false
    }
})

@jordanmkoncz
Copy link

Thanks @augustoabreu, I was having the same problem and I'm using Redux to manage my navigation state, and your solution worked for me.

@augustoabreu
Copy link

augustoabreu commented Jun 26, 2017

@RobertSheaO yes, when key property is set to null the root navigator will manage the action. Right now we can't reset from/to nested navigators, there is the #1384 PR that seems to resolve this problem. Take a look, maybe support and up the PR if you think the same. Good luck!

@jordanmkoncz you are welcome

@opp100
Copy link

opp100 commented Jul 26, 2017

I found a stupid solution, but its working probably. #1715

@carsonwah
Copy link

carsonwah commented Aug 18, 2017

@iRoachie 's solution works for me. However, if I create screen as component, I cannot hide TabNavigator in static navigationOptions, which works before.

const AppNavigator = TabNavigator(
  {
    MainTab: {
      // screen: HomeNavigator, <---- Using this works originally
      screen: ({ navigation }) =>
        <HomeNavigator screenProps={{ rootNavigation: navigation }} />,
      navigationOptions: {
        tabBarLabel: 'Home',
        tabBarIcon: ({ tintColor, focused }) => (
          <Icon name='home' size={26} color={tintColor} />
        ),
      },
    },
  }
)

const HomeNavigator = StackNavigator(
  {
    Home: { screen: Home },
    SubView: { screen: SubView },
});

class SubView extends Component {
  static navigationOptions = {
    title: 'SubView', // <---- this works
    headerLeft: null, // <---- this works
    tabBarVisible: false, // <---- only this fails
  };
}

I'm not sure if it is a bug or not. Really frustrated now.

@spencercarli
Copy link
Member

Hi! In an effort to get the hundreds of issues on this repo under control I'm closing issues tagged as questions. Please don't take this personally - it's simply something we need to do to get the issues to a manageable point. If you still have a question I encourage you to re-read the docs, ask on StackOverflow, or ask on the #react-navigation Reactiflux channel. Thank you!

@asciiman
Copy link

asciiman commented Sep 4, 2017

Here's how I do it with redux:

const initialState = resetRoute('SplashTab');

function resetRoute(routeName, state) {
  return TabNavigator.router.getStateForAction(
    NavigationActions.reset({
      index: 0,
      key: null,
      actions: [NavigationActions.navigate({ routeName })]
    }),
    state
  );
}

function navigate(routeName, state) {
  return TabNavigator.router.getStateForAction(
    NavigationActions.navigate({ routeName }),
    state
  );
}

export default function(state = initialState, action) {
  switch (action.type) {
  case LOCAL_QUESTION_CREATED:
    const rootState = resetRoute('AppTab', state);
    const screen1 = navigate('SettingsScreen', rootState);
    return navigate('ProfileScreen', screen1);
  }
  return TabNavigator.router.getStateForAction(action, state) || state;
}

@Johncy1997
Copy link

DriverStack(drawernav)
    -- searchStack(stacknav) and (initialroute)
          -screen1
          -screen2
    -- bookingstack
           - screen1
           - screen2
     ....

current:


now i move to screen1(searchStack) -> screen2(searchStack) -> screen1(bookingStack)
now i press back it goes to screen2(searchStack)

expectation:


screen1(searchStack) -> screen2(searchStack) -> (now first i want to clear the stack history of searchStack and then move to (screen1)bookingStack)
now i press back it directly should go to initialRoute of DriverStack.

Someone please tell me some idea to get this.

Currently i am trying to get this by:


const resetStack = StackActions.reset({
        index:this.props.items.findIndex(item=>item.key===this.props.activeItemKey),
        //key:this.props.activeItemKey,
        actions:[
            NavigationActions.navigate({
                routeName:menuDetail.routeName}) //Here the routename passed as "bookingstack" and produce error as There is no route defined for key bookingstack.
        ]
    });
return this.props.navigation.dispatch(resetStack);

or if i give like this,

this.props.navigation.navigate(menuDetail.routeName) //move to next stack but searchStack history is not reset

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests