How to navigate between different nested stacks in react navigation

React NativeReact Navigation

React Native Problem Overview


The Goal

Using react navigation, navigate from a screen in a navigator to a screen in a different navigator.

More Detail

If I have the following Navigator structure:

  • Parent Navigator
  • Nested Navigator 1
    • screen A
    • screen B
  • Nested Navigator 2
    • screen C
    • screen D

how do I go from screen D under nested navigator 2, to screen A under nested navigator 1? Right now if I try to navigation.navigate to screen A from screen D there will be an error that says it doesn't know about a screen A, only screen C and D.

I know this has been asked in various forms in various places on this site as well as GitHub(https://github.com/react-navigation/react-navigation/issues/983, https://github.com/react-navigation/react-navigation/issues/335#issuecomment-280686611) but for something so basic, there is a lack of clear answers and scrolling through hundreds of GitHub comments searching for a solution isn't great.

Maybe this question can codify how to do this for everyone who's hitting this very common problem.

React Native Solutions


Solution 1 - React Native

In React Navigation 5, this becomes much easier by passing in the screen as the second parameter:

navigation.navigate('Nested Navigator 2', { screen: 'screen D' });

You can also include additional levels if you have deeply nested screens:

navigation.navigate('Nested Navigator 2', {
    screen: 'Nested Navigator 3', params: {
        screen: 'screen E'
    }
});

Solution 2 - React Native

Update: For React Navigation v5, see @mahi-man's answer.


You can use the third parameter of navigate to specify sub actions.

For example, if you want to go from screen D under nested navigator 2, to screen A under nested navigator 1:

this.props.navigation.navigate(
    'NestedNavigator1', 
    {}, 
    NavigationActions.navigate({ 
        routeName: 'screenB' 
    })
)

Check also: https://reactnavigation.org/docs/nesting-navigators/

Solution 3 - React Native

React Navigation v3:

Navigation.navigate now takes one object as the parameter. You set the stack name then navigate to the route within that stack as follows...

navigation.navigate(NavigationActions.navigate({
    routeName: 'YOUR_STACK',
    action: NavigationActions.navigate({ routeName: 'YOUR_STACK-subRoute' })
}))

Where 'YOUR_STACK' is whatever your stack is called when you create it...

  YOUR_STACK: createStackNavigator({ subRoute: ... })

Solution 4 - React Native

On React Navigation v5 you have here all the explanation:

https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator

Route definition

function Root() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Profile" component={Profile} />
      <Stack.Screen name="Settings" component={Settings} />
    </Stack.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator>
        <Drawer.Screen name="Home" component={Home} />
        <Drawer.Screen name="Root" component={Root} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}

Instruction

navigation.navigate('Root', { screen: 'Settings' });

Solution 5 - React Native

In React Navigation v5, you can do something like:

navigation.navigate('Root', {
  screen: 'Settings',
  params: {
    screen: 'Sound',
    params: {
      screen: 'Media',
    },
  },
});

In the above case, you're navigating to the Media screen, which is in a navigator nested inside the Sound screen, which is in a navigator nested inside the Settings screen.

Solution 6 - React Native

In React Navigation 3

@ZenVentzi, Here is the answer for multi-level nested navigators when Nested Navigator 1 has Nested Navigator 1.1.

  • Parent Navigator
    • Nested Navigator 1
      • Nested Navigator 1.1
        • screen A
        • screen B
    • Nested Navigator 2
      • screen C
      • screen D

We can just inject NavigationActions.navigate() several times as needed.

  const subNavigateAction = NavigationActions.navigate({
    routeName: 'NestedNavigator1.1',
    action: NavigationActions.navigate({
      routeName: 'ScreenB',
      params: {},
    }),
  });
  const navigateAction = NavigationActions.navigate({
    routeName: 'NestedNavigator1',
    action: subNavigateAction,
  });
  this.props.navigation.dispatch(navigateAction);

UPDATE For React Navigation 5, please check @mahi-man's answer above. https://stackoverflow.com/a/60556168/10898950

Solution 7 - React Native

Complete freedom: singleton w/ navigationOptions

If you have a situation where you have multiple navigation stacks and sub stacks, this can be frustrating to know how to get a reference to the desired stack given how React Navigation is setup. If you were simply able to reference any particular stack at any given time, this would be much easier. Here's how.

  1. Create a singleton that is specific to the stack you want to reference anywhere.

     // drawerNavigator.js . (or stackWhatever.js)
     const nav = {}
     export default {
       setRef: ref => nav.ref = ref,
       getRef: () => nav.ref
     }
    
  2. Set the reference on desired navigator using navigatorOptions

     import { createBottomTabNavigator } from 'react-navigation'
     import drawerNavigation from '../drawerNavigator'
    
     const TabNavigation = createBottomTabNavigator(
       {
         // screens listed here
       },
       {
         navigationOptions: ({ navigation }) => {
           // !!! secret sauce set a reference to parent
           drawerNavigation.setRef(navigation)
           return {
             // put navigation options
           }
         }
       }
     )
    
  3. Now you can reference drawerNavigator anywhere inside or outside

    // screen.js
    import drawerNavigator from '../drawerNavigator'
    
    export default class Screen extends React.Component {
      render() {
        return (
          <View>
            <TouchableHighlight onPress={() => drawerNavigator.getRef().openDrawer()}>
              <Text>Open Drawer</Text>
            </TouchableHighlight>
          </View>
        )
      }
    }
    

Explanation

Within Step 2, a Tab Navigator is one of the screens within a Drawer Navigator. Tab Navigator needs to close the drawer but also anywhere within your app, you can call drawerNavigator.getRef().closeDrawer() after this step is performed. You are not limited to having direct access to props.navigation after that step.

Solution 8 - React Native

If nothing else works (as in my case), just do:

Main/Root/App.js:

<StackNavigator ref={(x) => (global.stackNavigator = x)} />

Anywhere:

global.stackNavigator.dispatch(
   NavigationActions.navigate({
       routeName: 'Player',
       params: { },
   }),
);

Solution 9 - React Native

try this,

Parent Navigator
  Nested Navigator 1
    screen A
    screen B
  Nested Navigator 2
    screen A
    screen C
    screen D

and then, there is no need to go A in 1 from D in 2, you can just go A from D both in 2, you can check here image or A stack navigator for each tab

Solution 10 - React Native

In React Navigation V5, you can do like this:

but remember to you placing this on the parent side

this.props.navigation.navigate(
          'Nested Navigator 1',
          {name: 'jane'},
          this.props.navigation.navigate('Screen A', {id: 2219}),
        );

Solution 11 - React Native

React Navigation v6


docs

function Home() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Feed" component={Feed} />
      <Tab.Screen name="Messages" component={Messages} />
    </Tab.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={Home}
          options={{ headerShown: false }}
        />
        <Stack.Screen name="Profile" component={Profile} />
        <Stack.Screen name="Settings" component={Settings} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

navigation.navigate('Home', { screen: 'Messages' });

Solution 12 - React Native

I've found also such solution here:

onPress={() =>
    Promise.all([
    navigation.dispatch(
        NavigationActions.reset({
            index: 0,
            // TabNav is a TabNavigator nested in a StackNavigator
            actions: [NavigationActions.navigate({ routeName: 'TabNav' })]
        })
    )
    ]).then(() => navigation.navigate('specificScreen'))
}

Solution 13 - React Native

In React Navigation v5

navigation.navigate('Home', {
   screen: 'Profile',
   params: {userID: 1}
 }
)

What If We Nest More?

Consider this structure:

NAVIGATOR:
  *StackA
    *ScreenC
    *ScreenD
  *StackB
    *ScreenI
    *StackE
      *ScreenF
      *StackG
        *ScreenJ
        *ScreenH

We want to get from ScreenC inside StackA all the way to ScreenH in StackB. We can actually chain the parameters together to access specific screens.

navigation.navigate('StackB',{
   screen: 'StackE',
   params: {
      screen: 'StackG',
      params: {
         screen: 'ScreenH'
      }
   }
  }
)

For more information

Solution 14 - React Native

This is another way to navigate to nested screen using Version: 5.x. It worked without any additional configuration. More info here: https://reactnavigation.org/docs/use-link-to

const linkTo = useLinkTo();
// ...
// Just call this
linkTo(`/main/sub/subB`);

Solution 15 - React Native

While working on a react-native project, i came across same situation. I have tried multiple ways in navigating to screen but failed.

After many trials, I tried passing parents navigation object to children and made a navigation function call and it worked.

Now coming to your issues, If you want to navigation from screen D to screen A do follow these steps.

-> Pass nested navigator 2 navigation props to its children using screenProps.

export default class Home extends Component {
    static navigationOptions = {
        header:null
    };

    constructor(props) {
        super(props);
        this.state = {
            profileData: this.props.navigation.state.params,
            route_index: '',
        }
    }

    render() {
        return (
            <ParentNavigator screenProps={this.props.navigation} />
        );
    }
}

export const ParentNavigator = StackNavigator({
  // ScreenName : { screen : importedClassname }
  Nested1: { screen: nested1 },
  Nested2: { screen : nestes1 }
});

export const nested1 = StackNavigator({
  ScreenA: { screen: screenA },
  ScreenB: { screen : screenB }
});

export const nested2 = StackNavigator({
  ScreenC: { screen: screenC },
  ScreenD: { screen : screenD }
});

You can receive the navigation in children using

const {navigate} = this.props.screenProps.navigation;

Now this navigate() can be used to navigate between children.

I accept that this process is little confusing but i couldn't find any solutions so had to go with this as i have to complete my requirement.

Solution 16 - React Native

 const subAction = NavigationActions.navigate({ routeName: 'SignInScreen' });
      AsyncStorage.clear().then(() =>
        this.props.navigation.navigate('LoggedOut', {}, subAction));

LoggedOut is the stack name where signIn screen is placed.

Solution 17 - React Native

My goal was to have the authentication screens all share the same background and the rest of the app using the regular stack transition.

After hours I've found the solution is to have the createStackNavigator() in the same file as your component wrapper. So that you can successfully expose the static router as the document stated. This will avoid the You should only render one navigator explicitly in your app warning and you can use this.props.navigation.navigate('AnyScreen') to navigate to any nested screen.

AuthRouter.js

export const AuthNavigationStack = createStackNavigator(
  {
    Login: {
      screen: Login
    },
    CreateAccount: {
      screen: CreateAccount
    }
  }
);

export default class AuthContainer extends React.Component {
  constructor( props ) {
    super( props );
  }

  static router = AuthNavigationStack.router;

  render() {
    return (
      <ImageBackground
        style={ {
          width: '100%',
          height: '100%'
        } }
        source={ require( '../Images/johannes-andersson-yosimite.jpg' ) }
        blurRadius={ 10 }
      >
        <StatusBar
          barStyle="dark-content"
          backgroundColor="transparent"
          translucent={ true }
        />
        <AuthNavigationStack navigation={ this.props.navigation } />
      </ImageBackground>
    );
  }
}

MessengerRouter.js

export const MessengerStackNavigator = createStackNavigator(
  {
    Chat: {
      screen: Chat,
    },
    User: {
      screen: User,
    },
  }
);

export default class MainContainer extends React.Component {
  constructor( props ) {
    super( props );
  }

  static router = MessengerStackNavigator.router;

  render() {
    return <MessengerStackNavigator navigation={ this.props.navigation } />;
  }
}

Router.js

import { createStackNavigator } from 'react-navigation';

import AuthRouter from './AuthRouter';
import MessengerRouter from './MessengerRouter';

export const RootNavigationStack = createStackNavigator( {
  AuthContainer: {
    screen: AuthRouter,
    navigationOptions: () => ( {
      header: null
    } )
  },
  MessengerRouter: {
    screen: MessengerRouter,
    navigationOptions: () => ( {
      header: null
    } )
  }
} );

RootContainer.js

import { RootNavigationStack } from '../Config/Router';

class RootContainer extends Component {

  render() {
    return <RootNavigationStack />;
  }
}

Notes:

  • Pass header: null from the RootNaviagtionStack to the nested stacks to remove the overlapping header

  • If you navigate from Nested A to Nested B and use the back button, it will return you to the first screen in Nested B. Not a big problem but I haven't figured out how to fix it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionizikandrwView Question on Stackoverflow
Solution 1 - React Nativemahi-manView Answer on Stackoverflow
Solution 2 - React NativeStackiaView Answer on Stackoverflow
Solution 3 - React NativePhil AndrewsView Answer on Stackoverflow
Solution 4 - React NativeRochadsouzaView Answer on Stackoverflow
Solution 5 - React NativeCam CHNView Answer on Stackoverflow
Solution 6 - React NativeHelga SokolovaView Answer on Stackoverflow
Solution 7 - React NativeKing FridayView Answer on Stackoverflow
Solution 8 - React Nativeiuliu.netView Answer on Stackoverflow
Solution 9 - React NativeHerbert_HBTView Answer on Stackoverflow
Solution 10 - React Nativehari antaraView Answer on Stackoverflow
Solution 11 - React NativeРоманView Answer on Stackoverflow
Solution 12 - React NativeAliakseiView Answer on Stackoverflow
Solution 13 - React NativeAbolfazlRView Answer on Stackoverflow
Solution 14 - React NativeFDiskView Answer on Stackoverflow
Solution 15 - React NativeHungrySoulView Answer on Stackoverflow
Solution 16 - React NativeRishav KumarView Answer on Stackoverflow
Solution 17 - React NativeSon LeView Answer on Stackoverflow