141

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.

1
  • 1
    Can you post your navigator stack code, and also if you're using redux navigation or not? Commented Apr 14, 2018 at 2:20

18 Answers 18

153

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'
    }
});
Sign up to request clarification or add additional context in comments.

9 Comments

You can even navigate in a deeper Navigation structure with params, e.g. Root -> Settings -> Sound -> Media: navigation.navigate('Root', { screen: 'Settings', params: { screen: 'Sound', params: { screen: 'Media' }}});
but how to use it with push function?
The nested params and with the specific screen name is the key! Thank you. This is not in the documentation.
What is 'Nested Navigator 2' in the answer and how to define it?
if the screens has unique names why the process isn't automatic? why we still have to include the route?
|
88

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/

7 Comments

What is 'NestedNavigator1' a reference to?
@niksn try this this.props.navigation.navigate('NestedNavigator1', {}, NavigationActions.navigate({ routeName: 'screenB', params: {param1: 'value1'} }))
In case of NestedNavigator1 has one more nested navigator inside called NestedNavigator1.1, with ScreenA1 and ScreenB1. How would that work if we want to navigate to NestedNavigator1.1, ScreenB1? Would it be possible? I'm using v.3.
What about in React Navigation v.5.0?
What are NavigationActions? It seems I can't import it from anythwere
|
20

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' });

10 Comments

Done and ty, @TT. 👍
this is correct but does not give a fluid transition.
You can even navigate in a deeper Navigation structure with params, e.g. Root -> Settings -> Sound -> Media: navigation.navigate('Root', { screen: 'Settings', params: { screen: 'Sound', params: { screen: 'Media' }}});
BUt what if I want to go back from another stack to another stack? I tried the from technique it works but the backArrow/backButton disappears in the screen to which i am navigating back.
For those who have issue with unexpected goBack(), add initial: false. E.g. navigation.navigate("InboxStack", {screen: "InboxDetails", initial: false})
|
20

In React Navigation v5/v6

Navigation to Specific Screen on a Stack

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

2 Comments

With TypeScript, modify the types to:Home: { screen: string; params: { userID: string } } | undefined;
Also valid for React Navigation v7
19

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: ... })

1 Comment

I've just copy-pasted the comment from the most-upvoted answer. - In case of NestedNavigator1 has one more nested navigator inside called NestedNavigator1.1, with ScreenA1 and ScreenB1. How would that work if we want to navigate to NestedNavigator1.1, ScreenB1? Would it be possible? I'm using v.3
9

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.

Comments

6

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' });

4 Comments

On My Home Stack, What if my initial route is Feed, and i used this technique, Then i cannot go to Feed stack anymore.
But when navigating cross stack are transitions like slide in and out working ? How is this possible to achieve ?
@AlauddinAhmed I also had this challenge, where a TabView had Stack Navigators in each tab. Navigating from nested stack to nested stack, worked, but the initial route would get squashed, and there was no way to go back. I discovered the solution here reactnavigation.org/docs/…, simply set the property initial to false in the navigate props eg. navigation.navigate('Home', { screen: 'Messages' , initial: false});
Steffan your solution of adding initial: false worked for me Thanks!
4

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

1 Comment

Where does NavigationActions come from? I can't import it from anywhere
3

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: { },
   }),
);

3 Comments

Getting error 'global.stackNavigator.dispatch' is undefined
Are you calling it instantly when the app loads? It needs to be after the <StackNavigator /> is rendered, so at least one render/stack frame afterwards
I am calling it on my local notification action to move the user to the particular screen so the app rendered stack navigator but still getting that error
3

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

Comments

2

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.

2 Comments

this is AWESOME!
This worked for me, except in React Navigation 5, you have to do <Drawer.Navigator screenOptions={({navigation}) => {[save your reference]; return {}}} />
2

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}),
        );

1 Comment

This is the only thing that would work for my case in React Navigation v5.0. Thank you!
1

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.

Comments

1

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'))
}

Comments

1

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`);

1 Comment

One can also use: <Link to={"/stack/nested-screen"}>Go to nested screen</Link>
1

I don't think it's a good idea to navigate through nested navigations, as it is slow and going back has many issues. A better approach is to add the screen to the current parent stack. So we will have the same stack screen in both <Stack.Navigator>

Comments

0
 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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.