I am using a combination of tab navigator, stack navigator, and switch nagivator in my react native app with react-navigation.
This works well, except I'd like to keep the bottom tabs in every screen. Currently if I navigate to UserProfile screen, then the bottom tabs go away.
App.js:
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedScreenStack },
MyProfile: { screen: ProfileScreenStack },
});
const UserStack = createStackNavigator(
{
UserProfile: { screen: userProfile },
Comments: { screen: comments }
}
);
const MainStack = createSwitchNavigator(
{
Home: TabStack,
User: UserStack,
Auth: AuthStack
},
{
initialRouteName: 'Home'
}
);
To solve this, I tried making a component out of the tab navigator and just importing it in userProfile.js, like <BottomTab />.
bottomTab.js:
const BottomTab = createBottomTabNavigator({
Feed: { screen: FeedScreenStack },
MyProfile: { screen: ProfileScreenStack },
})
export default BottomTab
but this doesn't work because in react-navigation 3 I have to set up the app container directly and I am not sure how to get around it. The only other solution I can think of is to create a custom component that is just a bar with buttons pointing to different pages, but I wonder if I can just use TabNavigator?
The recommended way is that a TabNavigation is the Top Item in your navigation stack. In each of the tabs you might have a different StackNavigation. If you use the SwitchNavigation for Auth which probably means a Login-Screen, you might put the SwitchNavigation at top with the two children Auth and Tab and include Home, User, Feed, etc. in different StackNavigations that are children of the TabNavigation. You could change for example as following:
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedScreenStack },
User: { screen: UserStack },
});
const UserStack = createStackNavigator({
UserProfile: { screen: userProfile },
Comments: { screen: comments },
MyProfile: { screen: ProfileScreenStack },
});
const MainStack = createSwitchNavigator({
Home: TabStack,
Auth: AuthStack
},
{
initialRouteName: 'Home'
});
Related
I am using react-navigation, I want to open a drawer from MyProfile screen, having the options to go to EditProfile screen and Settings screen. But I can't figure out how to open a drawer when I click on MyProfile's header button.
App.js:
const MyProfileStack = createStackNavigator({
MyProfile: {
screen: profile,
navigationOptions: ({navigation}) => {
return {
title: "My Profile",
headerRight: (
<Icon type="evilicon" name="navicon" size={40}
onPress={() => navigation.dispatch(DrawerActions.openDrawer())}/>
)
};
}
}
})
const DrawerStack = createDrawerNavigator({
Edit: { screen: EditProfileStack }
Settings: { screen: SettingsStack }
})
const EditProfileStack = createStackNavigator({
EditProfile: {
screen: editProfile,
navigationOptions: ({navigation}) => {
return {
title: "Edit Profile",
headerLeft: (
<Icon type="evilicon" name="chevron-left" size={50}
onPress={() => navigation.navigate("MyProfile")}/>
)
};
}
}
});
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedStack },
Profile: { screen: MyProfileStack },
});
const MainStack = createSwitchNavigator(
{
Home: TabStack,
Drawer: DrawerStack
},
{
initialRouteName: 'Home'
}
);
const AppContainer = createAppContainer(MainStack);
Solution
You need to put your MyProfileStack in DrawerStack as below.
const DrawerStack = createDrawerNavigator({
MyProfile: { screen: MyProfileStack }
Edit: { screen: EditProfileStack }
Settings: { screen: SettingsStack }
})
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedStack },
Profile: { screen: DrawerStack },
});
const AppContainer = createAppContainer(MainStack);
You can use various combination.
Why?
SwitchNavigator resign other Screens when you switch to another one. So you cannot call drawer from the screen already resigned.
p.s: You can use navigation events if you want to refresh your screen when change the screen. Use onWillFocus.
I am using a combination of tab navigator, stack navigator, and switch nagivator in my react native app with react-navigation. Note that I have to put each screen of the tab navigator inside its own stack navigator in order to use the built in header feature.
The functionalities work. But I end up getting 2 headers for Feed and Profile pages, like this:
I just want each screen to have its own header and the comment screen to have a back button. I know the code is not very clean and putting all these navigators inside each other uses a lot of overhead. So what is the best way to achieve this?
App.js
const FeedScreenStack = createStackNavigator({
FeedStack: {
screen: feed,
navigationOptions: {
headerTitle: "Feed"
}
}
});
const ProfileScreenStack = createStackNavigator({
ProfileStack: {
screen: profile,
navigationOptions: {
headerTitle: "My Profile"
}
}
})
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedScreenStack },
Profile: { screen: ProfileScreenStack }
});
const AppStack = createStackNavigator({
Tab: TabStack,
Comments: {
screen: comments,
navigationOptions: {
headerTitle: "Comments"
},
}
});
const MainStack = createSwitchNavigator(
{
Home: AppStack,
Auth: AuthStack
},
{
initialRouteName: 'Home'
}
);
const AppContainer = createAppContainer(MainStack);
You said that you want the Comments screen to have its own header (like all the other screens) and a back button. What specifically should it go back to? Understanding the structure of the navigation will make it easier to design.
It would be cleaner to have your AppStack actually just be your TabStack. Adding in the Comments screen on the same level as TabStack likely isn't helping your multiple header issue.
Here I show how you could cut out AppStack entirely and nest Comments in either the Profile of Feed tabs, depending on your need.
const FeedScreenStack = createStackNavigator({
FeedStack: {
screen: feed,
navigationOptions: {
headerTitle: "Feed"
}
},
// if you want Comments to go back to "Feed"
Comments: {
screen: comments,
navigationOptions: {
headerTitle: "Comments"
},
}
});
const ProfileScreenStack = createStackNavigator({
ProfileStack: {
screen: profile,
navigationOptions: {
headerTitle: "My Profile"
}
},
// if you want Comments to go back to "Profile"
Comments: {
screen: comments,
navigationOptions: {
headerTitle: "Comments"
},
}
})
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedScreenStack },
Profile: { screen: ProfileScreenStack }
});
const MainStack = createSwitchNavigator(
{
Home: TabStack,
Auth: AuthStack
},
{
initialRouteName: 'Home'
}
);
const AppContainer = createAppContainer(MainStack);
However, if you want Comments to in fact live above Profile and Feed, you should either make it its own tab, or change it into a Modal on the top level. Let me know if this is more like what you need and I can post more specifics!
Try to modify AppStack Like this:
Edited:
i forgot to include it inside navigationOptions. try.
const AppStack = createStackNavigator({
Tab: {
screen:TabStack,
navigationOptions: () => ({
headerMode: 'none',
// or this
header: null
})
},
Comments: {
screen: comments,
navigationOptions: {
headerTitle: "Comments"
},
}
},
);
I am using react-navigation with my react-native app. I have to put TabNavigators inside StackNavigator to use the built in header feature. See below.
app.js
const FeedScreenStack = createStackNavigator({
Feed: {
screen: feed,
navigationOptions: {
headerTitle: "Feed"
}
}
});
const ProfileScreenStack = createStackNavigator({
Feed: {
screen: profile,
navigationOptions: {
headerTitle: "My Profile"
}
}
})
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedScreenStack },
Profile: { screen: ProfileScreenStack }
});
const MainStack = createSwitchNavigator(
{
Home: TabStack,
Auth: AuthStack
},
{
initialRouteName: 'Home'
}
);
feed.js:
import React from 'react';
import { View } from 'react-native';
class feed extends React.Component {
constructor(props) {
super(props);
}
render(){
return (
<View style={{flex:1}}>
...
</View>
)
}
}
export default feed;
When clicking on profile, the app can move to profile screen. But it will not move to feed screen when clicking on feed. There are no warnings or errors, the app simply does not respond to when I click on feed. What am I doing wrong?
The problem is that you have defined repeted route names at many places, try giving different names
Do it like this
const FeedScreenStack = createStackNavigator({
FeedStack: {
screen: feed,
navigationOptions: {
headerTitle: "Feed"
}
}
});
const ProfileScreenStack = createStackNavigator({
ProfileStack: {
screen: profile,
navigationOptions: {
headerTitle: "My Profile"
}
}
})
const TabStack = createBottomTabNavigator({
Feed: { screen: FeedScreenStack },
Profile: { screen: ProfileScreenStack }
});
const MainStack = createSwitchNavigator(
{
Home: TabStack,
Auth: AuthStack
},
{
initialRouteName: 'Home'
}
);
I have a app that need both StackNavigator and TabNavigator. The logic is:
const App = StackNavigator({
Welcome: {
screen: Welcome
},
Login: {
screen: Login
},
Register: {
screen: Register
},
Auth: {
screen: Auth
},
Home: {
screen: Main
},
});
const Main = TabNavigator({
Home: { screen: Home },
Dash: { screen: Dash},
Myself: { screen: Myself},
});
const Pages = StackNavigator({
Share: { screen: Share},
About: { screen: About},
Service: {screen: Service}
});
I can correctly handle how to jump from App to App, but in the TabNavigator in screen Myself I want to jump to the StackNavigator Pages, if I add it directly to Main, it doesn't work.
So how can I achieve this?
What you need to do is something similar to how you put a TabNavigator inside of a StackNavigator with Main. You can also put a StackNavigator inside of a TabNavigator.
In this case, you want to use your Pages navigator as the MySelf route on your Main TabNavigator, and instead of having a page MySelf on the TabNavigator route, put MySelf as the initial route on the Pages StackNavigator.
It will look like something like this:
...
const Pages = StackNavigator({
Index: { screen: MySelf },
Share: { screen: Share },
About: { screen: About },
Service: { screen: Service },
});
const Main = TabNavigator({
Home: { screen: Home },
Dash: { screen: Dash},
Myself: { screen: Pages},
});
I am trying to navigate from one of the tabs in TabNavigator to a screen in the StackNavigator with a reset action. Here is (abbreviated) code:
...
const FriendsNavigator = StackNavigator({
Friends: { screen: Friends },
})
const TabsNavigator = TabNavigator({
Home: { screen: HomeNavigator },
Schedule: { screen: ScheduleNavigator },
Friends: { screen: FriendsNavigator },
Activity: { screen: ActivityNavigator }
})
const Main = StackNavigator({
Login: { screen: Login },
Tabs: { screen: TabsNavigator }
})
AppRegistry.registerComponent('Main', () => Main);
I'm trying to get from Friends in FriendsNavigator to Login in Main and reset the stack (as if the user was logging out). Does anyone have any ideas?
I'm very new to all this, but I think you need to have a master (my word) navigator. I make mine a stackNavigator, and then hide it when I don't want it - likewise with the tabNavigator.
Here is my code that works:
const MainNavigator = StackNavigator({
loginForm: { screen: LoginForm },
main: {
screen: TabNavigator({
groupMain: { screen: GroupMain },
feedback: { screen: Feedback },
settings: { screen: Settings },
groupScreen: {
screen: TabNavigator({
groupScreens: { screen: GroupPage},
feedbackInput: { screen: FeedbackInput}
})
}
})
}
}, {
navigationOptions: {
tabBarVisible: false,
header: null
}
});