How to navigate between different nested stacks in react navigation - react-native

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.

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

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/

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

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

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.

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

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

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

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

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

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

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.

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

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.

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.

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

Related

How do I create an embedded Stack navigator inside a React Native formSheet modal?

Like so:
I'm running react-navigation v4.
First you have to follow the tutorial on how to set up a react-navigation modal, the one that has a jump animation and doesn't look like the native formSheet. You have to set up a stack navigator with your root navigator as one child and the modal as another:
And it scales, because you can have more than one of these modals as children.
The code for this is the following:
const RootNavigator = createStackNavigator(
{
index: { screen: AppNavigator },
[NC.SCREEN_ROOM_INFO]: { screen: RoomInfoNavigator },
[NC.SCREEN_CHAT_CREATE]: { screen: RoomCreateNavigator },
[NC.SCREEN_CHAT_SEARCH]: { screen: ChatSearchNavigator },
[NC.SCREEN_CHAT_GIF_PICKER]: { screen: GifPickerNavigator }
},
{
mode: 'modal',
headerMode: 'none',
transitionConfig: () => ({
transitionSpec: {
duration: 0
}
}),
transparentCard: true
}
)
Then you need to implement these, from my example, 4 navigators that will be displayed as modals each like so:
// Here you'll specify the screens you'll navigate in this modal, starting from index.
const RoomInfoStack = createStackNavigator({
index: { screen: NavigableRoomInfo },
[NC.SCREEN_ROOM_ROSTER]: { screen: NavigableRoomRoster },
[NC.SCREEN_ROOM_NOTIFICATION_PREFERENCES]: { screen: NavigableRoomNotificationPreferences },
[NC.SCREEN_ROOM_EDIT]: { screen: NavigableRoomEdit }
})
type NavigationComponent<T = any> = {
navigation?: NavigationScreenProp<NavigationState, T>
}
type Props = NavigationComponent
// THIS code is from the react-navigation tutorial on how to make a react-navigation modal:
// https://reactnavigation.org/docs/4.x/custom-navigators/#extending-navigators
class RoomInfoNavigator extends React.Component<Props> {
static router = {
...RoomInfoStack.router,
getStateForAction: (action, lastState) => {
// check for custom actions and return a different navigation state.
return RoomInfoStack.router.getStateForAction(action, lastState)
}
}
constructor(props) {
super(props)
this.onClose = this.onClose.bind(this)
}
onClose() {
this.props.navigation?.goBack()
}
// And here is the trick, you'll render an always open RN formSheet
// and link its dismiss callbacks to the goBack action in react-navigation
// and render your stack as its children, redirecting the navigator var to it in props.
render() {
return (
<Modal
visible={true}
animationType={'slide'}
supportedOrientations={['portrait', 'landscape']}
presentationStyle={'formSheet'}
onRequestClose={() => this.onClose()}
onDismiss={() => this.onClose()}
>
<RoomInfoStack {...this.props} />
</Modal>
)
}
}
export { RoomInfoNavigator }
This export is what our root stack imported before. Then you just need to render the screens, I have a pattern that I do to extract the navigation params to props in case this screen is ever displayed without navigation:
const NavigableRoomInfo = (props: NavigationComponent<RoomInfoProps>) => {
const roomInfo = props.navigation!.state!.params!.roomInfo
const roomInfoFromStore = useRoomFromStore(roomInfo.id)
// Here I update the navigation params so the navigation bar also updates.
useEffect(() => {
props.navigation?.setParams({
roomInfo: roomInfoFromStore
})
}, [roomInfoFromStore])
// You can even specify a different Status bar color in case it's seen through modal view:
return (
<>
<StatusBar barStyle="default" />
<RoomInfo roomInfo={roomInfoFromStore} navigation={props.navigation} />
</>
)
}
Sources:
https://reactnavigation.org/docs/4.x/modal
https://reactnavigation.org/docs/4.x/custom-navigators/#extending-navigators

how to set initialRouteName dynamically in the react-native

how to give dynamic initial route name in the react-navigation? if the unit exists we have to redirect to another route or else we have to take user another route.
Note: I'm creating a bottom tab navigator in which I have to set an initial route to that particular bottom tab navigator.
(Not the authentication flow)
import React, {Component} from 'react';
import {createAppContainer} from 'react-navigation';
import {createMaterialBottomTabNavigator} from 'react-navigation-material-bottom-tabs';
... imports
function getInitialScreen() {
AsyncStorage.getItem('unit')
.then(unit => {
return unit ? 'Home' : 'secondTab';
})
.catch(err => {
});
}
const TabNavigator = createMaterialBottomTabNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: {
.....navigation options
},
},
secondTab: {
screen: secondTab,
},
},
{
initialRouteName: getInitialScreen(),
},
);
export default createAppContainer(TabNavigator);
See according to the docs, initialRoute name should not be a async func .
So ideally what you should do is , anyways you need a splashscreen for your app right, where you display the logo and name of app. Make that page the initialRoute and in its componentDidMount, check for the async function and navigate to ddesired page.
Like what ive done :
createSwitchNavigator(
{
App: TabNavigator,
Auth: AuthStack,
SplashScreen: SplashScreen,
},
{
initialRouteName: 'SplashScreen',
},
),
And inside SplashScreen im doing :
componentDidMount(){
if (token) {
this.props.navigation.navigate('App');
} else {
this.props.navigation.navigate('Auth');
}
}
Hope its clear. Feel free for doubts
As you can see here:
If you need to set the initialRouteName as a prop it is because there
is some data that you need to fetch asynchronously before you render
the app navigation. another way to handle this is to use a
switchnavigator and have a screen that you show when you are fetching
the async data, then navigate to the appropriate initial route with
params when necessary. see docs for a full example of this.
Take a look at here.
You'll find more description!
Also quick fix for this situation is check your condition inside SplashScreen componentDidMount() function
Example of SplashScreen :
componentDidMount(){
AsyncStorage.getItem('unit')
.then(unit => {
if(unit){
this.props.navigation.navigate('Home')
}else{
this.props.navigation.navigate('secondTab')
}
})
.catch(err => {
});
}
You can check the condition on the main page or App.js
render() {
const status = get AsyncStorage.getItem('unit');
if(status != null)
{ return <Home/> }
else
{ return <AnotherScreen/> }
}
But we can switch between pages if we use stacknavigator or switchnavigator..
We cant goto the particular tabs directly according to my knowledge. (Correct me if I am wrong).
The official documentation gives you this example to achieve pretty much what you want:
isSignedIn ? (
<>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</>
) : (
<>
<Stack.Screen name="SignIn" component={SignInScreen} />
<Stack.Screen name="SignUp" component={SignUpScreen} />
</>
)
Ok So in your navigation page create state and change its value accordingly AsyncStorage like
render() {
const status = get AsyncStorage.getItem('unit');
if(status != null)
{ setState({ name : 'Home'}) }
else
{ setState({ name : 'anotherTab'}) }
}
then pass that state to tabNavigation
initialRouteName: this.state.name,
and this state , setState functions are classed based so you have to use useState instead to initial state on your page

React navigation undefined params

I'm trying to pass params into a new screen, and implemented it like mentioned here.
I have the following TouchableOpacity button.
<TouchableOpacity
onPress={() => {
this.props.navigation.navigate('SomeScreen', {
title: 'Title',
subTitle: 'Subtitle',
});
}}
>
On the other page (let's call it Somescreen), I have the following:
render() {
const { navigation } = this.props;
const title = navigation.getParam('title');
}
But title above is undefined:
{ params: undefined, routeName: "Somescreen", key: "id-xx" }
My rootStack:
const RootStack = createStackNavigator({
SomescreenA: { screen: SomescreenA },
SomescreenB: { screen: SomescreenB },
}, { headerMode: 'none' });
Why are my params undefined in a new screen?
If you face a situation where your target screen get undefined params, probably you have a nested navigation stack.
Here you have to pass params to the navigate method in this way:
navigation.navigate('Root', {
screen: 'Settings',
params: { user: 'jane' },
});
For more information read this page in the official docs:
https://reactnavigation.org/docs/nesting-navigators/#navigating-to-a-screen-in-a-nested-navigator
In my specific case, I was calling a nested navigator, so I had to manage how send those params to their specific screen, so I did this:
Send params this way...the regular way:
navigation.navigate(
'OrderNavigator',
{itemSelected},
);
Then, from navigator stack I did this:
const OrderNavigator = ({route: {params}}) => {
return (
<Stack.Navigator initialRouteName="Order">
<Stack.Screen name="Order" component={Order} options={{headerShown: false}} initialParams={params} />
</Stack.Navigator>
);
};
And that's it. Then from the screen I got them like this:
const Order = ({route}) => {
const {itemSelected} = route.params;
const {first_name, last_name} = itemSelected;
return (...)
}
I've, unfortunately, encountered cases where navigate(route, params, ...) wouldn't pass the params object, just like you did.
As a workaround, I use the other variant - navigate({routeName, params, action, key}) that you can find here. It always works.
The accepted answer workaround did not work for me, so apparently if you use children to render your component (in screen options) and pass route as a prop, it works
if you are on react navigation v6^ use the useRoute hook to access the params object
const route = useRoute();
useRoute is a hook that gives access to the route object. It's useful when you cannot pass the route prop into the component directly, or don't want to pass it in case of a deeply nested child.
below is an implementation of this
import { useNavigation, useRoute } from '#react-navigation/native';
import { Pressable, Text } from 'react-native';
function Screen1() {
const navigation = useNavigation();
return (
<Pressable
onPress={() => {
navigation.navigate('Screen2', { caption: 'hey' });
}}
>
<Text> Go to Screen 2 </Text>
</Pressable>
);
}
function Screen2() {
const route = useRoute();
return <Text>{route.params.caption}</Text>;
}

How do I access a prop passed to TabNavigator within tab screen?

I have a tabnavigator like so
var TabNavigation = createBottomTabNavigator({
NearbyScreen: {
screen: Nearby
},
FindScreen:{
screen: LandmarkNavigation
},
NotificationScreen:{
screen: Notifications
},
MyProfile:{
screen: MyProfile
}
})
that is rendered in the component
render() {
//console.log(this.props);
var nearbyLocations = this.props.locationsNearby;
return(
<TabNavigation thisThing="thisThingValue" />
)
}
How do I access the value of the prop I passed on inside one of it's tabs?
I solved it with screenProps:
return(
<TabNavigation screenProps={thing} />
)
Which made it accessible in the navigator tab view via this.props.screenProps
Try accessing through here this.props.navigation.state.params.thisThing

How do i make a TabNavigator button push a modal screen with React Navigation

Using the React Navigation tab navigator https://reactnavigation.org/docs/navigators/tab how do I make one of the tab buttons push the screen up as a full screen modal? I see the stack navigator has a mode=modal option. how do I get that mode to be used when clicking on the TakePhoto tab button? Clicking on it currently still shows the tab bar on the bottom.
const MyApp = TabNavigator({
Home: {
screen: MyHomeScreen,
},
TakePhoto: {
screen: PhotoPickerScreen, // how can I have this screen show up as a full screen modal?
},
});
Actually, there is no support in react-navigation to change the way of presentation on the fly from default to modal (see the discussion about this here). I ran into the same issue and solved it by using a very top StackNavigator with headerMode set to none and mode set to modal:
const MainTabNavigator = TabNavigator(
{
Tab1Home: { screen: Tab1Screen },
Tab2Home: { screen: Tab2Screen }
}
);
const LoginRegisterStackNavigator = StackNavigator({
Login: { screen: LoginScreen }
});
const ModalStackNavigator = StackNavigator({
MainTabNavigator: { screen: MainTabNavigator },
LoginScreenStackNavigator: { screen: LoginRegisterStackNavigator }
}, {
headerMode: 'none',
mode: 'modal'
});
This allows me to do the following (using redux) in Tab1Screen and Tab2Screen to bring up the modal view from wherever I want:
this.props.navigation.navigate('LoginScreenStackNavigator');
Not sure if this is still relevant for you, but i've managed to find away to achieve this.
So i've managed to get it working by using the tabBarComponent inside the tabNavigatorConifg, you can stop the tab navigation from navigating depending on the index.
tabBarComponent: ({jumpToIndex, ...props, navigation}) => (
<TabBarBottom
{...props}
jumpToIndex={index => {
if (index === 2) {
navigation.navigate('camera')
}
else {
jumpToIndex(index)
}
}}
/>
)
Once you've done this, my method of showing the view modally on top of the tab views was to put the tabnavigator inside of a stacknavigatior and then just navigate to a new screen inside of the stacknavigator.
react-navigation's bottomTabNavigator has a tabBarOnPress navigation option you can use to override tab presses:
https://reactnavigation.org/docs/en/bottom-tab-navigator.html#tabbaronpress
const AppContainer = createStackNavigator(
{
default: createBottomTabNavigator(
{
TAB_0: Stack0,
TAB_1: Stack1,
TAB_2: Stack2,
TAB_3: View // plain rn-view, or any old unused screen
},
{
defaultNavigationOptions: {
// other tab navigation options...
tabBarOnPress: ({ navigation, defaultHandler }) => {
if (navigation.state.key === 'TAB_3') {
navigation.navigate('tabToOpenAsModal');
} else {
defaultHandler();
}
}
}
}
),
tabToOpenAsModal: {
screen: TabToOpenAsModalScreen
}
},
{
mode: 'modal',
headerMode: 'none'
}
);
If you nest your tab navigator within a stack navigator with a modal, you can open this when the tab bar button is pressed. Since the modal was opened and not the tab, when the modal is closed the app returns to the screen that was visible before the modal tab was pressed.
One way to make the tab bar go away is to hide the tabBar with visible: false:
const MyApp = TabNavigator({
Home: {
screen: MyHomeScreen,
},
TakePhoto: {
screen: PhotoPickerScreen,
navigationOptions: {
tabBar: {
visible: false,
},
},
},
});
However, that does not seem to trigger any transition to fullscreen, which I guess is desired?
Another option could be to wrap PhotoPickerScreen inside a new StackNavigator and set that navigator to mode='modal'.
You might have to trigger the navigation to that modal from onPress on the tabItem somehow (eg. navigation.navigate('TakePhoto').)
Note, I'm trying to wrap my head around how best to structure navigation myself, so …
Third option, implementing a StackNavigator as parent, then adding the MyApp TabNavigator as the first route inside of it, could be the most flexible solution. Then the TakePhoto screen would be on the same level as the TabNavigator, allowing you to route to it from wherever.
Interested to hear what you come up with!
I suggest two solution
First one is about hide it
For seconde one please read that: https://reactnavigation.org/docs/hiding-tabbar-in-screens
<Tab.Screen
name={Routes.CREATE_ANNOUNCEMENT_SCREEN}
// name={Routes.TEST_SCREEN}
options={{
.
.
.
tabBarVisible: false, <----- solution 1
tabBarButton: (props) => ( <----- or solution 2
<TouchableOpacity
{...props}
onPress={() => {
navigation.navigate(Routes.DETAILS_SCREEN);
}}
/>
),
}}
component={CreateAnnouncementScreen}
/>
Docs are patchy in some areas, but here it is:
export default class HomeScene extends Component {
static navigationOptions = {
title: 'foo',
header:{
visible: true
}
}
....
}