Using react navigation, navigate from a screen in a navigator to a screen in a different navigator.
If I have the following
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: { },
}),
);
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'
}
});
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.
In React Navigation 3
@ZenVentzi, Here is the answer for multi-level nested navigators when Nested Navigator 1
has Nested Navigator 1.1
.
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
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/
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.