123

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.

Godfrey
  • 1,001
  • 14
  • 17
izikandrw
  • 1,703
  • 3
  • 14
  • 23

17 Answers17

133

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'
    }
});
Harry B
  • 2,864
  • 1
  • 24
  • 44
mahi-man
  • 4,326
  • 2
  • 25
  • 36
  • 9
    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' }}});` – Mika Jul 29 '20 at 15:42
  • 7
    but how to use it with `push` function? – Nameer Dec 03 '20 at 08:59
  • The nested params and with the specific screen name is the key! Thank you. This is not in the documentation. – Georges Feb 11 '21 at 23:05
  • 9
    What is 'Nested Navigator 2' in the answer and how to define it? – user2185592 Aug 10 '21 at 16:14
  • Can you do dispatch / push here so it refresh when the params are changing ? – Tahola Nov 08 '21 at 09:55
  • 3
    if the screens has unique names why the process isn't automatic? why we still have to include the route? – Zakthedev Dec 30 '21 at 23:48
  • Didn't react-navigation used to find the route automatically? I upgraded from v4 and now have to explicitly tell the app how to get around. I'm sure they had their reasons, but this was the most magical thing about react-navigation. – rob5408 Aug 30 '22 at 15:28
  • It works. but when I press the back from `screen D` I want it to come back to the previous screen that we were on `screen A` NOT the `Screen C`. – Ali Aref Jul 19 '23 at 02:01
85

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/

Stackia
  • 2,110
  • 17
  • 23
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: ... })
Max Phillips
  • 6,991
  • 9
  • 44
  • 71
  • 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 – ZenVentzi Aug 16 '19 at 06:46
  • Thanks Its works for me React-navigation-V4 – Saurabh Chavan Jul 26 '22 at 12:28
19

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' });
Rochadsouza
  • 888
  • 10
  • 10
  • Done and ty, @TT. – Rochadsouza Apr 11 '20 at 14:56
  • this is correct but does not give a fluid transition. – afrojuju_ Apr 13 '20 at 01:34
  • @afrojuju_ I have a fluid transition. – Rochadsouza Apr 13 '20 at 20:45
  • @Rochadsouza, what if for example I have another screen under the `Drawer.Navigator` let's call it `Data` and I want to navigate to it from `Settings` screen. `navigation.navigate('App', { screen: 'Data' });` doesn't seem to work. – Keselme Jul 21 '20 at 06:40
  • 1
    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' }}});` – Mika Jul 29 '20 at 15:45
  • 14
    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. – Aldor Mar 02 '21 at 07:16
  • @Rochadsouza Root screen disappear if i don't focus it at the start – Alauddin Ahmed Aug 17 '22 at 15:13
  • @Aldor - sorry for necro, but I upvoted your comment then saw a good answer down further below. Consider including the screen you want to access from both navigators IN both navigators - e.g., if I want to access `Screen B` from two places i can with this: Nav 1: `Screen A`, `Screen B`. Nav 2: `Screen B`, `Screen C`. Won't work for everything, but if you were already hard-coding a route, seems reasonable, and works for my use case. – Kelton Temby Feb 15 '23 at 00:52
  • Any workaround to having the hardware back header button disappear? – Hyetigran Apr 13 '23 at 15:55
  • For those who have issue with unexpected goBack(), add initial: false. E.g. navigation.navigate("InboxStack", {screen: "InboxDetails", initial: false}) – The1993 Jul 14 '23 at 07:36
11

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

Abolfazl Roshanzamir
  • 12,730
  • 5
  • 63
  • 79
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.

Cam CHN
  • 3,377
  • 1
  • 19
  • 12
5

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' });
Роман
  • 479
  • 6
  • 7
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

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: { },
   }),
);
iuliu.net
  • 6,666
  • 6
  • 46
  • 69
  • Getting error 'global.stackNavigator.dispatch' is undefined – Chandni Apr 14 '21 at 07:10
  • Are you calling it instantly when the app loads? It needs to be after the `` is rendered, so at least one render/stack frame afterwards – iuliu.net Apr 14 '21 at 13:54
  • 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 – Chandni Apr 16 '21 at 05:45
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

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.

King Friday
  • 25,132
  • 12
  • 90
  • 84
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}),
        );
Hari Antara
  • 51
  • 1
  • 5
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.

David Schumann
  • 13,380
  • 9
  • 75
  • 96
HungrySoul
  • 1,151
  • 2
  • 17
  • 31
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'))
}
David Schumann
  • 13,380
  • 9
  • 75
  • 96
Aliaksei
  • 1,094
  • 11
  • 20
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`);
FDisk
  • 8,493
  • 2
  • 47
  • 52
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.

Rishav Kumar
  • 4,979
  • 1
  • 17
  • 32
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.

Son Le
  • 138
  • 1
  • 1
  • 8