I have implement react native navigation with 4 tabstack. Every tabstack is with multiple pages, When I moved from first page to next page or next stack. It works fine. but when I moved back to first page of the first stack and click on button of the page. it will move to last visited page of the last visited stack. I am not sure why it is happening.
I am putting my navigation code below
const stackNavigatorConfiguration = {
mode: "card",
defaultNavigationOptions: {
headerStyle: { backgroundColor: Colors.HeaderColor, borderBottomWidth: 0 },
headerTintColor: "#0055FF",
headerTitleStyle: {
fontSize: 20,
fontFamily: Constants.FontFamily,
fontWeight: "bold"
},
headerBackTitle: null,
barStyle: { backgroundColor: Colors.HeaderColor}
}
};
/* User Profile ---------------------------------------------------------------------------*/
const profileTabScreens = {};
profileTabScreens[Constants.Screen.MyProfile] = { screen: UserProfileScreen };
profileTabScreens[Constants.Screen.OrderHistory] = { screen: OrderHistoryScreen };
const profileStack = createStackNavigator(
profileTabScreens,
stackNavigatorConfiguration
);
profileStack.navigationOptions = ({ navigation }) => ({
tabBarIcon: ({ tintColor }) => (
<TabBarItem
icon={Icons.User}
tintColor={tintColor}
routeName={navigation.state.routeName}
/>
),
title:"User"
});
/* Cart ------------------------------------------------------------------------ */
const cartsTabScreens = {};
cartsTabScreens[Constants.Screen.OrderPreview] = { screen: OrderPreviewScreen };
cartsTabScreens[Constants.Screen.OrderSchedulePickup] = { screen: OrderSchedulePickupScreen };
cartsTabScreens[Constants.Screen.OrderConfirm] = { screen: OrderConfirmScreen };
cartsTabScreens[Constants.Screen.AddAddress] = { screen: AddAddressScreen };
cartsTabScreens[Constants.Screen.OrderThankyou] = { screen: OrderThankyouScreen };
const cartsStack = createStackNavigator(
cartsTabScreens,
stackNavigatorConfiguration
);
cartsStack.navigationOptions = ({ navigation }) => ({
tabBarIcon: ({ tintColor }) => (
<TabBarItem
icon={Icons.Cart}
tintColor={tintColor}
routeName={navigation.state.routeName}
/>
),
title:"Carts"
});
/*Deal/Service ------------------------------------------------------------------- */
const dealsTabScreens = {};
dealsTabScreens[Constants.Screen.Service] = { screen:ServicesListScreen };
dealsTabScreens[Constants.Screen.ShopListByService] = { screen:ShopListByServiceScreen };
const dealsStack = createStackNavigator( dealsTabScreens, stackNavigatorConfiguration);
dealsStack.navigationOptions = ({ navigation }) => ({
tabBarIcon: ({ tintColor }) => (
<TabBarItem
icon={Icons.ICCollection}
tintColor={tintColor}
routeName={navigation.state.routeName}
/>
),
title: "Services"
});
/* Home Stack------------------------------------------------------------*/
const homeTabScreens = {};
homeTabScreens[Constants.Screen.Home] = { screen: HomeScreen };
homeTabScreens[Constants.Screen.Vendor] = { screen: VendorScreen };
const homeStack = createStackNavigator( homeTabScreens, stackNavigatorConfiguration);
homeStack.navigationOptions = ({ navigation }) => ({
tabBarIcon: ({ tintColor }) => (
<TabBarItem
icon={Icons.ICBadgeHome}
tintColor={tintColor}
routeName={navigation.state.routeName}
/>
),
title: "Home",
});
/*------------------------------------------------------------*/
const tabScreens = {};
tabScreens[Constants.Screen.Home] = { screen: homeStack };
tabScreens[Constants.Screen.Service] = { screen: dealsStack };
tabScreens[Constants.Screen.Carts] = { screen: cartsStack };
tabScreens[Constants.Screen.MyProfile] = { screen: profileStack };
const mainTab = createMaterialBottomTabNavigator(tabScreens, {
initialRouteName: Constants.Screen.Home,
activeColor: Colors.BottomMenuColor,
inactiveColor: Colors.Gray,
barStyle: { backgroundColor: "#fff" }
});
const screens = {};
screens[Constants.Screen.Launch] = { screen: LaunchScreen };
screens[Constants.Screen.Auth] = { screen: AuthScreen };
screens[Constants.Screen.AuthOTP] = { screen: AuthOTPScreen };
screens[Constants.Screen.AuthPassword] = { screen: AuthPasswordScreen };
screens[Constants.Screen.UserRegisterDetail] = { screen: UserRegisterDetailScreen };
//screens[Constants.Screen.OrderHistory] = { screen: OrderHistoryScreen };
//screens[Constants.Screen.MyProfile] = { screen: UserProfileScreen };
screens[Constants.Screen.Home] = { screen: mainTab };
const mainStack = createStackNavigator(screens, {
initialRouteName: Constants.Screen.Launch,
activeColor: Colors.AppColor,
inactiveColor: Colors.Gray,
labelStyle: Styles.TabbarLabel,
headerMode: "none"
});
export default createAppContainer(mainStack);
Related
Using nested stacks when I go back to my homescreen, my homescreen briefly shows, then the app quits. Instead of hardcoding the route to go back to, how can I go back to my homescreen without quitting the app?
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
}
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
}
onBackPress = () => {
const { dispatch } = this.props;
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "Home" })]
});
this.props.navigation.dispatch(resetAction);
};
App navigator:
const withHeader = (
screen: Function,
routeName: string,
Header
): StackNavigator =>
createStackNavigator(
{
[routeName]: {
screen,
navigationOptions: ({ routeName, props }) => ({
header: props => <Header {...props} />
})
}
},
{
initialRoute: "Home",
transparentCard: true,
cardStyle: {
backgroundColor: "transparent",
opacity: 1
},
transitionConfig: () => ({
containerStyle: {
backgroundColor: "transparent"
}
})
}
);
const routes = {
VideoEpisodes: {
screen: withHeader(VideoEpisodesScreen, "Video Episodes", DrawerHeader)
},
TestYourself: {
screen: withHeader(TestYourselfScreen, "Test Yourself", DrawerHeader)
},
MyResults: {
screen: withHeader(MyResultsScreen, "My Results", DrawerHeader)
},
BookmarkedVideos: {
screen: withHeader(
BookmarkedVideosScreen,
"Bookmarked Videos",
DrawerHeader
)
},
About: {
screen: withHeader(AboutScreen, "About", DrawerHeader)
}
};
const NestedDrawer = createDrawerNavigator(routes, config);
const MainStack = createStackNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: ({ props }) => ({
header: props => <BasicHeader {...props} />
})
},
Drawer: {
screen: NestedDrawer,
navigationOptions: ({ props }) => ({
header: () => null
})
},
VideoPlayer: {
screen: VideoPlayerScreen,
navigationOptions: ({ props }) => ({
header: props => <BasicHeader {...props} />
})
}
},
{
initialRoute: "Home",
transparentCard: true,
cardStyle: {
backgroundColor: "transparent",
opacity: 1
},
transitionConfig: () => ({
containerStyle: {
backgroundColor: "transparent"
}
})
}
);
onBackPress = () => {
const { dispatch } = this.props;
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "Home" })]
});
this.props.navigation.dispatch(resetAction);
return true
};
My createSwitchNavigator has 3 pages: Login (no header). After login, it sends to the main page where I build my bottom, tab, stack, and drawer navigator.
const MainTabNavigator = createBottomTabNavigator({
Home,
Tenants,
WorkOrders: {
screen: WorkOrders,
navigationOptions: {
title: 'Work Orders'
}
}
}, {
navigationOptions: ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
if (routeName === 'WorkOrders') {
return {
headerTitle: 'Work Orders'
};
}
return {
headerTitle: routeName
};
}
});
const MainStackNavigator = createStackNavigator({
MainTabNavigator
}, {
defaultNavigationOptions: ({ navigation }) => {
return {
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
onPress={() => navigation.openDrawer()}
name="md-menu"
size={30}
/>
)
};
}
});
const AppDrawerNavigator = createDrawerNavigator({
iRent: {
screen: MainStackNavigator
}
});
const AppSwitchNavigator = createSwitchNavigator({
Login: { screen: Login },
Main: { screen: AppDrawerNavigator },
TenantDetails: {
screen: TenantDetails,
navigationOptions: () => {
return {
headerTitle: 'Tenant'
};
}
},
});
const AppContainer = createAppContainer(AppSwitchNavigator);
From the tenants, I navigate to the TenantDetails page, but in the TenantDetails the header is not showing. Why?
The switch navigator doesn't have a header. You can use a stack navigator instead.
Sample Code:
const AppStackNavigator = createStackNavigator({
Login: {
screen: Login,
navigationOptions:{
header: null // to override the header, because even if you don't specify the header title, a header will be shown.
}
},
Main: {
screen: AppDrawerNavigator,
navigationOptions:{
header: null
}
},
TenantDetails: {
screen: TenantDetails,
navigationOptions: {
headerTitle: 'Tenant',
headerLeft: null // If you want to override the back button, use this.
}
},
});
const AppContainer = createAppContainer(AppStackNavigator);
I'm new in react native and I created a bottom tab navigator. I have 3 menus: Home, Tenants, and WorkOrders. How can I change the WorkOrders to display the button name and header as "Work Orders" instead of "WorkOrders"?
const MainTabNavigator = createBottomTabNavigator({
Home,
Tenants,
WorkOrders
}, {
navigationOptions: ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
return {
headerTitle: routeName
};
}
});
const MainStackNavigator = createStackNavigator({
MainTabNavigator
}, {
defaultNavigationOptions: ({ navigation }) => {
return {
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
onPress={() => navigation.openDrawer()}
name="md-menu"
size={30}
/>
)
};
}
});
const AppDrawerNavigator = createDrawerNavigator({
Menu: {
screen: MainStackNavigator
}
});
const AppSwitchNavigator = createSwitchNavigator({
Login: { screen: Login },
Main: { screen: AppDrawerNavigator }
});
const AppContainer = createAppContainer(AppSwitchNavigator);
Thanks
You can do like this:
const MainTabNavigator = createBottomTabNavigator({
...,
WorkOrders: {
screen: WorkOrders,
navigationOptions: {
title: 'Work Orders'
// You can check more options here: https://reactnavigation.org/docs/en/bottom-tab-navigator.html#navigationoptions-for-screens-inside-of-the-navigator
}
}
},{
// BottomTabNavigatorConfig
})
You can do the same with other react-navigation's API
I have a screen which has tab-bar navigation where each screen is of type stack navigation with a couple of screens defined in each. When I navigate from FamilyMembers to SingleContact screen I don't want to see the navigation bar with the back button on top. I want my view (the blue one) in single contact to start from the top. But it appears although I set the header to null! Please help.
//------------------- Single Contact Screen----------//
import { Text, AsyncStorage, Image, FlatList, Alert, ActivityIndicator, Platform, StyleSheet, View } from 'react-native';
import { Icon, Container, Spinner, Content, Left, Right, Header, ListItem } from 'native-base'
import profileService from '../services/Api/ProfileService';
import { SafeAreaView } from 'react-navigation';
HEADER_MAX_HEIGHT = 100
HEADER_MIN_HEIGHT = 60
PROFILE_IMAGE_MAX_HEIGHT = 80
PROFILE_IMAGE_MIN_HEIGHT = 40
export default class SingleContact extends Component {
constructor(props) {
super(props);
this.state = { userName: "", contacts: [], userID: "", cookie: null, memberShips: [] };
}
async componentDidMount() {
}
onDataLoaded(result, userName) {
}
render() {
return (
<SafeAreaView>
<View style={{ flex: 1 }}>
//--------------------App.js navigation setup --------------------------//
const FamilyMembersStack = createStackNavigator({
FamilyMembers: {
screen: FamilyMembers,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Family members",
}
}
},
SingleContact: {
screen: SingleContact,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Contact"
}
}
},
}
, {
mode: 'modal',
headerMode: 'none'
});
const HomeScreenStack = createStackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
},
FamilyMembersStack: {
screen: FamilyMembersStack,
navigationOptions: ({ navigation }) => {
return {
header: null
}
}
},
AttendanceHistory: {
screen: AttendanceHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Attendance history"
}
}
},
OrderHistory: {
screen: OrderHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Order history"
}
}
}
});
HomeScreenStack.navigationOptions = {
tabBarLabel: 'My info',
tabBarIcon: ({ tintColor }) => (
<FaIcon name="user" size={20} color={tintColor} />
),
};
const ScheduleScreenStack = createStackNavigator({
Schedule: {
screen: ScheduleScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
}
});
ScheduleScreenStack.navigationOptions = {
tabBarLabel: 'Find a class',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-calendar" size={20} color={tintColor} />
),
};
const ShopScreenStack = createStackNavigator({
Shop: {
screen: ShopScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
}
});
ShopScreenStack.navigationOptions = {
tabBarLabel: 'Get a pass',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-basket" size={20} color={tintColor} />
),
};
const NotificationsScreenStack = createStackNavigator({
Notifications: {
screen: NotificationsScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
}
});
NotificationsScreenStack.navigationOptions = {
tabBarLabel: 'Notifications',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-alert" size={20} color={tintColor} />
),
};
const EventsStack = createStackNavigator({
Events: {
screen: Events,
navigationOptions: ({ navigation }) => {
return {
tabBarLabel: "Events",
tabBarIcon: ({ tintColor }) => (
<Icon name="md-calendar" size={20} />
),
headerLeft: (
<Icon name="md-menu" style={{ paddingLeft: 10 }}
onPress={() => navigation.openDrawer()}
size={30} />
)
}
}
}
});
EventsStack.navigationOptions = {
tabBarLabel: 'Events',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-calendar" size={20} color={tintColor} />
),
};
const DashboardTabNavigator = createBottomTabNavigator({
HomeScreenStack,
ScheduleScreenStack,
ShopScreenStack,
NotificationsScreenStack
},
{
navigationOptions: ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
return {
header: null,
headerTitle: routeName,
}
},
tabBarOptions: {
activeTintColor: 'white',
inactiveTintColor: 'silver',
labelStyle: {
fontSize: 12,
},
style: {
backgroundColor: 'rgba(24,130,201,1);',
},
}
}, { initialRouteName: HomeScreenStack }
);
const DashboardStackNavigator = createStackNavigator({
DashboardTabNavigator: DashboardTabNavigator
});
const AppDrawerNavigator = createDrawerNavigator({
Dashboard: {
screen: DashboardStackNavigator
}
}, {
contentComponent: props => <DrawerContent {...props} />
});
const AppSwitchNavigator = createSwitchNavigator({
AuthLoading: AuthLoadingScreen,
Login: { screen: Login },
Dashboard: { screen: AppDrawerNavigator }
}, {
initialRouteName: 'AuthLoading',
}
);
const AppContainer = createAppContainer(AppSwitchNavigator);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
Did you already modify your FamilyMembersStack inside HomeScreenStack like this?
const HomeScreenStack = createStackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
},
// modify this Stack
FamilyMembersStack:{
screen: FamilyMembersStack,
navigationOptions: ({ navigation }) => {
return {
header: null
}
}
}
AttendanceHistory: {
screen: AttendanceHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Attendance history"
}
}
},
OrderHistory: {
screen: OrderHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Order history"
}
}
}
});
Follow up answer, remove the following. so that the header will render on the designated screen:
export default class SingleContact extends Component {
static navigationOptions = {
header: null, // remove this
}
constructor(props) {
super(props);
this.state = { userName: "", contacts: [], userID: "", cookie: null, memberShips: [] };
}
async componentDidMount() {
}
onDataLoaded(result, userName) {
}
render() {
//------------------------------//
const FamilyMembersStack = createStackNavigator({
FamilyMembers: {
screen: FamilyMembers,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Family members",
header:null
}
}
},
SingleContact: {
screen: SingleContact,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Contact",
header:null // and remove this
}
}
},
});
I have Login and MAIN screen with 2 tabs...I'm passing user to MAIN screen with navigate('MAIN',{user: user} and I couldn't get that user in my MAIN with this.props.navigation.getParam('user'). My error is: undefined
When I debug with :
Reactotron.log(this.props); I'm getting undefined in my Main screen in constructor.
My code in App.js where is routes
const Routes = createStackNavigator(
{
Login: {
screen: Login,
navigationOptions: ({ navigation }) => ({
header: null,
}),
},
Main: {
screen: MainScreenRoutes,
navigationOptions: ({navigation}) => ({
header: null,
}),
},
},
{
initialRouteName: 'Login',
headerMode: 'screen',
navigationOptions: {
...HeaderStyles,
animationEnabled: true
}
}
);
export default Routes;
Code in MainRoutes:
let headerDefaultNavigationConfig = {
header: props => <CustomHeader {...props} />,
...HeaderStyles
};
const Tab1 = createStackNavigator(
{
Domov: {
screen: HomeScreen,
navigationOptions: {
},
},
},
{
navigationOptions: ({ navigation }) => ({
...headerDefaultNavigationConfig
}),
}
);
const Tab2 = createStackNavigator(
{
Dnevnik: {
screen: Diary,
navigationOptions: {
},
}
},
{
navigationOptions: ({ navigation }) => ({
...headerDefaultNavigationConfig
}),
}
);
const bottomTabs = createBottomTabNavigator(
{
Domov: Tab1,
Dnevnik: Tab2,
},
{
initialRouteName: "Domov",
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Domov') {
//iconName = `home${focused ? '' : '-outline'}`;
iconName='home';
} else if (routeName === 'Dnevnik') {
//iconName = `ios-calendar${focused ? '' : '-outline'}`;
iconName='ios-calendar';
}
// if focused return view with line
if(focused) {
return (
<View style={styles.item}>
<Icon name={iconName} style={{fontSize: 20, color: '#FFF'}} />
<View style={styles.line}></View>
</View>
);
} else {
return(
<Icon name={iconName} style={{fontSize: 20, color: '#FFF'}} />
)
}
},
}),
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: 'white',
showLabel: false,
inactiveTintColor: '#4C2601',
style: {
backgroundColor: '#033D51',
},
labelStyle: {
fontSize: 12,
lineHeight: 30,
},
},
swipeEnabled: true,
});
const All = createStackNavigator(
{
"Home":{
screen: bottomTabs,
navigationOptions: {
header: null,
},
},
"MyProfil":{
screen: MyProfil,
navigationOptions: ({ navigation }) => ({
...headerDefaultNavigationConfig,
headerTitle: 'Moj profil',
}),
},
"Help": {
screen: Help,
navigationOptions: ({ navigation }) => ({
...headerDefaultNavigationConfig,
headerTitle: 'Pomoč',
}),
}
},
{
initialRouteName: 'Home',
headerMode: 'screen',
navigationOptions: {
...HeaderStyles,
animationEnabled: true
}
}
);
export default All;
Code in HomeScreen: That alert gives me undefined
constructor(props) {
super(props);
let user = props.navigation.getParam('user');
alert(user);
}
Code in Login.js where I navigate to that screen with tabs;
var obj = {
id: json.user.id,
lastname: json.user.lastname,
name: json.user.name,
email: json.user.email,
user: json.user.user,
};
_storeData(obj);
setTimeout(() => {
navigate("Main",{user: JSON.stringify(obj)});
},1300);
This is good :
this.props.navigation.navigate("HomeScreen", { user :user });
try this :
let user = props.navigation.state.params.user ;
EDIT :
as the constructor is called only one time for each app start try this
import _ from "lodash";
...
constructor(props){ super(props) ; console.log("main constructor ") ; ... }
componentWillReceiveProps(nextProps) {
console.log(JSON.stringify(nextProps.navigation.state.params))
if (_.has(nextProps, "navigation.state.params.user")) {
console.log(nextProps.navigation.state.params.user );
this.setState({ user: nextProps.navigation.state.params.user })
}
}
EDIT 2
in my createStackNavigator in dont have
navigationOptions: { header: null},
just simple stack1: { screen: stack1 },
but in my stack screen component i have this
export default class stack1 extends React.PureComponent {
static navigationOptions = ({ navigation }) => ({ header: null });
constructor (props) {
super(props);
this.state = { };
}
componentDidMount() {
this.setState({ obsToEdit: this.props.navigation.state.params.obs, dataready: true });
}
}