I am updating my react-native app to use react navigation 6 and I'm trying to figure out how to connect to a screen.
The screen I'm trying to link/navigate to uses a bottomtabnavigator, and looks like this:
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
export const PatientScreen = () => {
const Tab = createBottomTabNavigator();
return (
<Tab.Navigator screenOptions={{ headerShown: false }} initialRouteName={'Visits'}>
<Tab.Screen name="Visits" component={VisitsTab}
options={{
tabBarLabel: 'Visits',
tabBarIcon: ({ color, size }) => (
<FontAwesome name="street-view" color={color} size={size} />
),
}}
/>
<Tab.Screen name="Chart" component={ChartTab}
options={{
tabBarLabel: 'Charts',
tabBarIcon: ({ color, size }) => (
<FontAwesome name="id-badge" color={color} size={size} />
),
}}
/>
<Tab.Screen name="Goals" component={GoalsTab}
options={{
tabBarLabel: 'Edit Goals',
tabBarIcon: ({ color, size }) => (
<FontAwesome name="trophy" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
);
}
I am trying to link to the above from within a screen that is part of a different navigator. That screen looks like this:
import { StyleSheet, Text, View, Tab, Button } from 'react-native';
import { PatientScreen } from './PatientScreen';
export const CaseloadScreen = ({navigation}) => {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Caseload</Text>
<Button title="Patient"
onPress={() => navigation.navigate('PatientScreen', { screen: 'Visits' })}
/>
</View>
);
}
When I click on the button above, I get this error:
The action 'NAVIGATE' with payload undefined was not handled by any navigator.
Do you have a screen named 'PatientScreen'?
So clearly I'm missing something, but it's unclear to me what that is. How do I make this PatientScreen which uses a bottomTabNavigator, linkable from the button link I listed above?
My navigator for the Caseload screen looks like this:
import React from 'react';
import { StyleSheet, View, Text, Button } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItemList,
DrawerItem,
} from '#react-navigation/drawer';
import { LoginScreen } from '../screens/LoginScreen';
import { CaseloadScreen } from '../screens/CaseloadScreen';
import { WeeklyScreen } from '../screens/WeeklyScreen';
import { ProfileScreen } from '../screens/ProfileScreen';
import { Ionicons, FontAwesome, MaterialCommunityIcons, AntDesign } from '#expo/vector-icons';
import { AvailablePatientScreen } from '../screens/AvailablePatientScreen';
const CustomDrawerContent = (props) => {
return (
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} style={{
activeTintColor: {
color: '#fff',
},
}} />
</DrawerContentScrollView>
);
}
const Drawer = createDrawerNavigator();
const DrawerNavigation = () => {
const icons = {
tintColor: '#fff',
size: 20,
}
return (
<Drawer.Navigator initialRouteName={'Caseload'}n
drawerContent={(props) => <CustomDrawerContent {...props} />}
screenOptions={{
labelStyle: {
color: '#fff',
},
inactiveTintColor: {
color: '#fff',
},
drawerStyle: {
backgroundColor: 'rgb(61,77,138)',
width: 240,
activeTintColor: 'rgb(61,77,138)',
activeBackgroundColor: '#fff',
inactiveTintColor: '#fff',
inactiveBackgroundColor: 'rgb(61,77,138)',
},
}}
>
<Drawer.Screen name="Caseload" component={CaseloadScreen} options={{
drawerIcon: () => (<Ionicons name="ios-home" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="Weekly Summary" component={WeeklyScreen} options={{
drawerIcon: () => (<FontAwesome name="bar-chart" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="Available RiverKids" component={AvailablePatientScreen} options={{
drawerIcon: () => (<FontAwesome name="child" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="My Profile" component={ProfileScreen} options={{
drawerIcon: () => (<AntDesign name="profile" size={icons.size} color={icons.tintColor} />)
}} />
{/* <Drawer.Screen name="Patient" component={PatientScreen} options={{
drawerIcon: () => (<FontAwesome name="bar-chart" size={icons.size} color={icons.tintColor} />)
}} /> */}
<Drawer.Screen name="Login" component={LoginScreen} options={{ title: 'Sign Out',
drawerIcon: () => (<MaterialCommunityIcons name="logout" size={icons.size} color={icons.tintColor} />)
}} />
</Drawer.Navigator>
);
}
export const Navigator = () => {
return (
<NavigationContainer>
<DrawerNavigation />
</NavigationContainer>
);
}
In your drawer navigator there is no screen defined with the name 'PatientScreen';
I can see a commented screen in your drawer navigator which has a name Patient and the component is PatientScreen. If you wish to navigate the Patient Screen from the drawer, do uncomment that code and then do the below
import { StyleSheet, Text, View, Tab, Button } from 'react-native';
export const CaseloadScreen = ({navigation}) => {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Caseload</Text>
<Button title="Patient"
onPress={() => navigation.navigate('Patient', { screen: 'Visits' })}
/>
</View>
);
}
Or else if you wish to navigate the PatientScreen only from the Caseload Screen, then create a Stack Navigator with the caseload and patient screen and then in the drawer navigator use that stack navigator in place of caseload screen
Related
I am getting a "Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined" error in my react native app after doing some refactoring. I am unclear what's causing the issue, but appears to be related to how I am importing/exporting something into the file below.
My root App() code looks like this:
import React, { useState, useEffect } from 'react';
import Navigator from './navigation/navigator';
import { LoginScreen } from './screens/LoginScreen';
export default function App() {
const [isLoggedIn, setIsloggedIn] = useState(false);
useEffect(() => {
setTimeout(() => {
setIsloggedIn(true);
}, 3000);
}, []);
return (
isLoggedIn ? (
<Navigator />
) : (
<LoginScreen />
)
);
}
And the navigator file I am importing into the above file looks like this:
import React from 'react';
import { StyleSheet, View, Feather } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItemList,
DrawerItem,
} from '#react-navigation/drawer';
import { LoginScreen } from '../screens/LoginScreen';
import { CaseloadScreen } from '../screens/CaseloadScreen';
import { PatientScreen } from '../screens/PatientScreen';
import { WeeklyScreen } from '../screens/WeeklyScreen';
import { ProfileScreen } from '../screens/ProfileScreen';
import { Ionicons, FontAwesome, MaterialCommunityIcons, AntDesign } from '#expo/vector-icons';
import { AvailablePatientScreen } from '../screens/AvailablePatientScreen';
const CustomDrawerContent = (props) => {
return (
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} style={{
activeTintColor: {
color: '#fff',
},
}} />
</DrawerContentScrollView>
);
}
const Drawer = createDrawerNavigator();
const DrawerNavigation = ({ navigation }) => {
const icons = {
tintColor: '#fff',
size: 20,
}
return (
<Drawer.Navigator initialRouteName={'Caseload'}
drawerContent={(props) => <CustomDrawerContent {...props} />}
options={{
headerLeft: (
<View>
<Feather name='menu' size={24}
onPress={() => navigation.toggleDrawer()}
color={'blue'} style={{}} />
</View>
),
}}
screenOptions={{
labelStyle: {
color: '#fff',
},
inactiveTintColor: {
color: '#fff',
},
drawerStyle: {
backgroundColor: 'rgb(61,77,138)',
width: 240,
activeTintColor: 'rgb(61,77,138)',
activeBackgroundColor: '#fff',
inactiveTintColor: '#fff',
inactiveBackgroundColor: 'rgb(61,77,138)',
},
}}
>
<Drawer.Screen name="Caseload" component={CaseloadScreen} options={{
drawerIcon: () => (<Ionicons name="ios-home" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="Weekly Summary" component={WeeklyScreen} options={{
drawerIcon: () => (<FontAwesome name="bar-chart" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="Available RiverKids" component={AvailablePatientScreen} options={{
drawerIcon: () => (<FontAwesome name="child" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="My Profile" component={ProfileScreen} options={{
drawerIcon: () => (<AntDesign name="profile" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="The Guys" component={TheGuysScreen} options={{
drawerIcon: () => (<Ionicons name="ios-chatbubbles" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="Patient" component={PatientScreen} options={{
drawerItemStyle: { display: 'none' },
headerShown: false,
}} />
<Drawer.Screen name="Login" component={LoginScreen} options={{ title: 'Sign Out',
drawerIcon: () => (<MaterialCommunityIcons name="logout" size={icons.size} color={icons.tintColor} />)
}} />
</Drawer.Navigator>
);
}
export default function Navigator() {
return (
<NavigationContainer>
<DrawerNavigation />
</NavigationContainer>
);
}
The one other import in the root is for LoginScreen, which looks like this:
import {
TouchableWithoutFeedback,
Text,
TextInput,
KeyboardAvoidingView,
Keyboard,
View,
Image,
Button,
} from 'react-native';
import styles from '../styles';
import { GradientButton } from '../components/GradientButton';
export const LoginScreen = (props) => {
console.log('props: ', props);
return (
<TouchableWithoutFeedback
onPress={Keyboard.dismiss}
>
<View style={styles.login.container}>
// Other code
</View>
</TouchableWithoutFeedback>
);
}
i have the following header.js
import React from 'react';
import {View, Text, StyleSheet, Image} from 'react-native';
import {MaterialCommunityIcons} from '#expo/vector-icons';
export default function header({navigation}, title) {
const openMenu =() => {
navigation.openDrawer()
}
return (
<View style={styles.header}>
<MaterialCommunityIcons name='menu'
size={24} color='black'
onPress={openMenu}
style={styles.icon}
/>
<View style={styles.headerTitle}>
<Image style={styles.logo} source={require('../assets/oau-ico-hat.png')}/>
<Text style={styles.headerText}>title={title}</Text>
{/* */}
</View>
</View>
)
}
const styles = StyleSheet.create({
header:{
width:'100%',
height: '100%',
flexDirection:'row',
alignItems:'center',
justifyContent:'center',
},
headerText:{
fontWeight: 'bold',
fontSize: 20,
color: '#333',
letterSpacing: 1,
marginTop:8,
marginHorizontal: 50,
marginLeft:10,
},
logo: {
width: 40,
height: 40,
},
icon:{
position:'absolute',
left: 0.7,
},
headerTitle:{
flexDirection:'row',
},
})
then i had the following App.js
const Drawer = createDrawerNavigator();
const DrawerNavigator=() => {
return (
<Drawer.Navigator
drawerContent={props => <DrawerContent {...props}
/>}
>
<Drawer.Screen name="Home" component={StackNavigator}
/>
<Drawer.Screen name="Faculties" component={Faculty}
/>
</Drawer.Navigator>
)
}
const Tab = createBottomTabNavigator();
const TabNavigator = ({navigation}) => (
<Tab.Navigator
screenOptions={{
headerStyle:{backgroundColor: "tomato" , elevation:0},
headerTintColor:"#fff",
headerTitleAlign:'center',
headerTitle: () => <Header navigation={navigation} title='O.A.U'/>
}}>
<Tab.Screen name="Home" component={DrawerNavigator} />
<Tab.Screen name="Faculties" component={Faculty}
/>
</Tab.Navigator>
)
const Stack = createStackNavigator();
const StackNavigator = ({navigation}) => (
<Stack.Navigator
screenOptions={{
headerStyle:{backgroundColor: "tomato" , elevation:0},
headerTintColor:"#fff",
headerTitleAlign:'center',
headerTitle: () => <Header navigation={navigation} title='O.A.U'/>
}}
>
<Stack.Screen name="Home" component={Home}
options={() => {<Header navigation={navigation} title='O.A.U'/>}}
/>
<Stack.Screen name="TabsBottom" component={Faculty}
/>
</Stack.Navigator>
);
const styles = StyleSheet.create({
header:{
alignItems:'center',
},
})
export default function App() {
return (
<NavigationContainer>
<TabNavigator/>
</NavigationContainer>
);
}
I have homeStack.js where in React Navigation V4 it was working as follow:any idea how can i make that work in V% react-navigation
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import Header from '../shared/header';
import Home from '../screens/homeScreen';
import Faculty from '../screens/faculties'
const screens ={
Home: {
screen: Home,
screenOptions:({ navigation } )=> {
return {
headerTitle: () => <Header navigation={navigation} title='O.A.U'/>,
}
}
},
Faculty: {
screen: Faculty,
navigatioptions:({ navigation } )=> {
return {
headerTitle: () => <Header navigation={navigation} title='O.A.U'/>,
}
}
}
}
const HomeStack = createStackNavigator();
export default HomeStack;
i have a drwer.js for the drawer meny as follow:
import React from "react";
import { StyleSheet, View } from "react-native";
import {
DrawerContentScrollView,
DrawerItem,
DrawerItemList,
} from "#react-navigation/drawer";
import {
Avatar,
Title,
Caption,
Paragraph,
Drawer,
Text,
TouchableRipple,
Switch,
} from "react-native-paper";
import { MaterialCommunityIcons, FontAwesome5 } from "#expo/vector-icons";
import Home from './homeStack'
export function DrawerContent({ ...props }) {
return (
<View style={{ flex: 1 }}>
<DrawerContentScrollView {...props}>
{/* <DrawerItemList {...props}/> */}
<DrawerItem
icon={({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
)}
label="Home"
onPress={() => props.navigation.navigate("Home")}
/>
<DrawerItem
icon={({ color, size }) => (
<FontAwesome5 name="university" color={color} size={size} />
)}
label="Faculties"
onPress={() => props.navigation.navigate("Faculties")}
/>
</DrawerContentScrollView>
</View>
);
}
my questions as follow:
1.how can i display the header in all screen as the header will include the menu burger that pulls the drawer menu?
2. when clicking on Faculties menu from tab the drawer menu is not working unless i click on home menu from tab navigation, is my nested navigation correct or where am I going wrong?
P/S: please note this my first time on developing mobile app using react.
you can have a look at github and see if you can help from there # https://github.com/sudani/Uni_app.git
after spending the last 2 days looking for answer i found great youtube tutorial, i frogot about rules posting link but here what i have managed to do:
removed all the stack screens, tab screens to separate file then import the file into App.js:
the file as follow:
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
import Icon from 'react-native-vector-icons/Ionicons';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import HomeScreen from './homeScreen'
import FacultyScreen from './faculties';
const HomeStack = createStackNavigator();
const FacultyStack = createStackNavigator();
const Tab = createMaterialBottomTabNavigator();
const MainTabScreen =() => (
<Tab.Navigator
initialRouteName="Home"
activeColor="#fff"
barStyle={{ backgroundColor: 'tomato' }}
>
<Tab.Screen
name="Home"
component={HomeStackScreen}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="home" color={color} size={26} />
),
}}
/>
<Tab.Screen
name="Faculty"
component={FacultyStackScreen}
options={{
tabBarLabel: 'Updates',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="bell" color={color} size={26} />
),
}}
/>
</Tab.Navigator>
)
export default MainTabScreen;
const HomeStackScreen =({navigation}) => (
<HomeStack.Navigator
screenOptions={{
headerStyle: { backgroundColor: "tomato", elevation: 0 },
headerTintColor: "#fff",
headerTitleAlign: "center",
headerShown:true,
}}
>
<HomeStack.Screen name= "Home" component={HomeScreen}
options={{
title:'Overview',
headerLeft: () => (
<Icon.Button name="ios-menu" size={26}
backgroundColor="tomato" onPress={() => navigation.openDrawer() }></Icon.Button>
)
}}
/>
</HomeStack.Navigator>
)
const FacultyStackScreen =({navigation}) => (
<FacultyStack.Navigator
screenOptions={{
headerStyle: { backgroundColor: "tomato", elevation: 0 },
headerTintColor: "#fff",
headerTitleAlign: "center",
headerShown:true,
}}
>
<FacultyStack.Screen name= "Faculty" component={FacultyScreen}
options={{
headerLeft: () => (
<Icon.Button name="ios-menu" size={26}
backgroundColor="tomato" onPress={() => navigation.openDrawer() }></Icon.Button>
)
}}
/>
</FacultyStack.Navigator>
)
then the App.js as follow:
import React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createDrawerNavigator} from '#react-navigation/drawer';
import MainTabScreen from './app/screens/MaintabScreen';
import { DrawerContent } from "./app/routes/drawer";
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer initialRouteName= "Home">
<Drawer.Navigator drawerContent={(props) => <DrawerContent {...props} />}>
<Drawer.Screen name="Home" component={MainTabScreen}/>
{/* <Drawer.Screen name="Faculty" component={FacultyStackScreen}/> */}
</Drawer.Navigator>
</NavigationContainer>
);
}
the drawer helper stayed the same as before
import React from "react";
import { StyleSheet, View } from "react-native";
import {
DrawerContentScrollView,
DrawerItem,
DrawerItemList,
} from "#react-navigation/drawer";
import {
Avatar,
Title,
Caption,
Paragraph,
Drawer,
Text,
TouchableRipple,
Switch,
} from "react-native-paper";
import { MaterialCommunityIcons, FontAwesome5 } from "#expo/vector-icons";
import Home from './homeStack'
export function DrawerContent({ ...props }) {
return (
<View style={{ flex: 1 }}>
<DrawerContentScrollView {...props}>
{/* <DrawerItemList {...props}/> */}
<DrawerItem
icon={({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
)}
label="Home"
onPress={() => props.navigation.navigate("Home")}
/>
<DrawerItem
icon={({ color, size }) => (
<FontAwesome5 name="university" color={color} size={size} />
)}
label="Faculties"
onPress={() => props.navigation.navigate("Faculty")}
/>
</DrawerContentScrollView>
</View>
);
}
I found this an Easy way of managing the nested navigation and it is almost what i wanted if anyone has better improvement suggestion that will be great
I am working on a dummy project for practice using react navigation material top tab. Everything is working fine, I just want to know is there any way to space around the tabs? I attached the output image of my code
Here is my code
import * as React from "react";
import { createDrawerNavigator } from "#react-navigation/drawer";
import AccountsScreen from "../screens/AccountsScreen";
import FavouritesScreen from "../screens/FavouritesScreen";
import HomeScreen from "../screens/HomeScreen";
import SettingsScreen from "../screens/SettingsScreen";
import TrendsScreen from "../screens/TrendsScreen";
import { createMaterialTopTabNavigator } from "#react-navigation/material-top-tabs";
import { Dimensions } from "react-native";
import Income from "../screens/Income";
import Expense from "../screens/Expense";
const Drawer = createDrawerNavigator();
const Tab = createMaterialTopTabNavigator();
CategoriesTabScreens = () => {
return (
<Tab.Navigator
initialRouteName="Income"
tabBarOptions={{
indicatorStyle: {
height: Dimensions.get("window").height,
backgroundColor: "#29416F",
},
activeTintColor: "#fff",
inactiveTintColor: "#333",
}}
>
<Tab.Screen name="Income" component={Income} />
<Tab.Screen name="Expense" component={Expense} />
</Tab.Navigator>
);
};
const AppDrawer = () => {
return (
<Drawer.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: true,
}}
>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Accounts" component={AccountsScreen} />
<Drawer.Screen name="Categories" component={CategoriesTabScreens} />
<Drawer.Screen name="Trends" component={TrendsScreen} />
<Drawer.Screen name="Favourites" component={FavouritesScreen} />
<Drawer.Screen name="Settings" component={SettingsScreen} />
</Drawer.Navigator>
);
};
export default AppDrawer;
Output
the result I want
Just use Style prop in Tab.navigator
Here is snack
https://snack.expo.io/#anthowm/drawer-navigation-%7C-react-navigation
const Tab = createMaterialTopTabNavigator();
const CategoriesTabScreens = () => {
return (
<Tab.Navigator
initialRouteName="Income"
tabBarOptions={{
indicatorStyle: {
height: Dimensions.get("window").height,
backgroundColor: "#29416F",
},
activeTintColor: "#fff",
inactiveTintColor: "#333",
}}
style={{paddingHorizontal: 24, marginTop: 40}}
>
<Tab.Screen name="Income" component={() => (<View style={{marginTop: 20}}><Text>INCOME</Text></View>)} />
<Tab.Screen name="Expense" component={() => (<View style={{marginTop: 20}}><Text>EXPENSE</Text></View>)} />
</Tab.Navigator>
);
};
I was trying to use my new created navigator stack on my bottom navigator tabs item so that I can use it instead of a regular screen.
So far I created the new stack navigator:
const FavoritesNav = () => {
return(
<FavoritesStack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: Colors.primaryColor,
},
headerTintColor: '#fff',
headerTitleStyle: {
fontSize: 17
}
}}>
<FavoritesStack.screen
name="Favorite"
component={FavoritesScreen}
/>
<FavoritesStack.screen
name="MealDetail"
component={MealDetailScreen}
/>
</FavoritesStack.Navigator>
);
};
And then, I tried to pass this on one of the item of my bottom navigator:
<MealsFavTabNavigator.Screen
name="Favorites"
component={FavoritesNav}
options={{
tabBarIcon: ({ focused, color, size }) => (
<Ionicons name="ios-star" size={25} color={focused ? "tomato" : "black"} />
)
}}
/>
This throws me an error: A navigator can only contain 'Screen' components as its diection children (found [object, object])
How can I pass my newly created stack to the bottom tab nav?
PS. Here's my complete code:
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { Ionicons } from '#expo/vector-icons';
import { Platform } from 'react-native';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
import CategoriesScreen from '../screens/CategoriesScreen';
import CategoryMealsScreen from '../screens/CategoryMealsScreen';
import MealDetailScreen from '../screens/MealDetailScreen';
import FavoritesScreen from '../screens/FavoritesScreen';
import HeaderButton from '../components/HeaderButton';
import { HeaderButtons, Item } from 'react-navigation-header-buttons';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { CATEGORIES } from '../data/dummy-data';
import Colors from '../constants/colors';
const MealsNav = createStackNavigator();
const MealsNavigator = () => {
return (
<MealsNav.Navigator
mode="modal"
screenOptions={{
headerStyle: {
backgroundColor: Colors.primaryColor,
},
headerTintColor: '#fff',
headerTitleStyle: {
fontSize: 17
}
}}
>
<MealsNav.Screen
name="Categories"
component={CategoriesScreen}
options={{
title: 'Meals Categories'
}}
/>
<MealsNav.Screen
name="CategoryMeals"
component={CategoryMealsScreen}
options={({ route }) => {
const catId = route.params.categoryId;
const selectedCategory = CATEGORIES.find((cat) => cat.id === catId);
return {
title: selectedCategory.title,
};
}}
/>
<MealsNav.Screen
name="MealDetail"
component={MealDetailScreen}
options={{
title: 'Meal Detail',
headerRight: () => (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title='Favorite'
iconName='ios-star'
onPress={() => console.log('Mark as the favorite')}
/>
</HeaderButtons>
),
}}
/>
</MealsNav.Navigator>
);
};
const MealsFavTabNavigator =
Platform.OS === 'android'
? createMaterialBottomTabNavigator()
: createBottomTabNavigator();
const getNavigationOptions = () => {
if (Platform.OS === 'ios') {
// Props for the ios navigator
return {
labeled: false,
initialRouteName: 'Meals',
tabBarOptions: {
activeTintColor: 'tomato',
inactiveTintColor: 'black',
},
};
}
// Props for android
return {
initialRouteName: 'Favorites',
activeColor: 'tomato',
inactiveColor: 'black',
barStyle: { backgroundColor: Colors.primaryColor },
shifting: true
};
};
const MealsTabNav = () => {
return (
<NavigationContainer>
<MealsFavTabNavigator.Navigator {...getNavigationOptions()} >
<MealsFavTabNavigator.Screen
name="Meals"
component={MealsNavigator}
options={{
tabBarIcon: ({ focused, color, size }) => (
<Ionicons name="ios-restaurant" size={25} color={focused ? "tomato" : "black"} />
)
}}
/>
<MealsFavTabNavigator.Screen
name="Favorites"
component={FavoritesNav}
options={{
tabBarIcon: ({ focused, color, size }) => (
<Ionicons name="ios-star" size={25} color={focused ? "tomato" : "black"} />
)
}}
/>
</MealsFavTabNavigator.Navigator>
</NavigationContainer>
);
};
const FavoritesStack = createStackNavigator();
const FavoritesNav = () => {
return(
<FavoritesStack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: Colors.primaryColor,
},
headerTintColor: '#fff',
headerTitleStyle: {
fontSize: 17
}
}}>
<FavoritesStack.screen
name="Favorite"
component={FavoritesScreen}
/>
<FavoritesStack.screen
name="MealDetail"
component={MealDetailScreen}
/>
</FavoritesStack.Navigator>
);
};
export default MealsTabNav;
Thanks for those who will help.
Guess you are importing FavoritesScreen but using FavoriteScreen in code.
import FavoritesScreen from '../screens/FavoritesScreen';
const FavoritesNav = () => {
<NavigationContainer>
<FavoritesStack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: Colors.primaryColor,
},
headerTintColor: '#fff',
headerTitleStyle: {
fontSize: 17
}
}}>
<FavoritesStack.screen
name="Favorite"
component={FavoritesScreen}
/>
<FavoritesStack.screen
name="MealDetail"
component={MealDetailScreen}
/>
</FavoritesStack.Navigator>
</NavigationContainer>
};
Hi am working on my tab navigator, so far so good until I tried to customize the tab navigator by adding icons and customized the colors:
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { Ionicons } from '#expo/vector-icons';
import CategoriesScreen from '../screens/CategoriesScreen';
import CategoryMealsScreen from '../screens/CategoryMealsScreen';
import MealDetailScreen from '../screens/MealDetailScreen';
import FavoritesScreen from '../screens/FavoritesScreen';
import HeaderButton from '../components/HeaderButton';
import { HeaderButtons, Item } from 'react-navigation-header-buttons';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { CATEGORIES } from '../data/dummy-data';
import Colors from '../constants/colors';
const MealsNav = createStackNavigator();
const MealsNavigator = () => {
return (
<MealsNav.Navigator
mode="modal"
screenOptions={{
headerStyle: {
backgroundColor: Colors.primaryColor,
},
headerTintColor: '#fff',
headerTitleStyle: {
fontSize: 17
}
}}
>
<MealsNav.Screen
name="Categories"
component={CategoriesScreen}
options={{
title: 'Meals Categories'
}}
/>
<MealsNav.Screen
name="CategoryMeals"
component={CategoryMealsScreen}
options={({ route }) => {
const catId = route.params.categoryId;
const selectedCategory = CATEGORIES.find((cat) => cat.id === catId);
return {
title: selectedCategory.title,
};
}}
/>
<MealsNav.Screen
name="MealDetail"
component={MealDetailScreen}
options={{
title: 'Meal Detail',
headerRight: () => (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title='Favorite'
iconName='ios-star'
onPress={() => console.log('Mark as the favorite')}
/>
</HeaderButtons>
),
}}
/>
</MealsNav.Navigator>
);
};
const MealsFavTabNavigator = createBottomTabNavigator();
const MealsTabNav = () => {
return (
<NavigationContainer>
<MealsFavTabNavigator.Navigator>
<MealsFavTabNavigator.Screen
name="Meals"
component={MealsNavigator}
screenOptions={() => ({
tabBarIcon: (tabInfo) => {
return <Ionicons name="ios-restaurant" size={25} color={tabInfo.tintColor} />
}
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'black',
}}
/>
<MealsFavTabNavigator.Screen
name="Favorites"
component={FavoritesScreen}
screenOptions={({ route }) => ({
tabBarIcon: (tabInfo) => {
return <Ionicons name="ios-star" size={25} color={tabInfo.tintColor} />
}
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'black',
}}
/>
</MealsFavTabNavigator.Navigator>
</NavigationContainer>
);
};
export default MealsTabNav;
As you can see here, I tried to add a screenOptions:
const MealsFavTabNavigator = createBottomTabNavigator();
const MealsTabNav = () => {
return (
<NavigationContainer>
<MealsFavTabNavigator.Navigator>
<MealsFavTabNavigator.Screen
name="Meals"
component={MealsNavigator}
screenOptions={() => ({
tabBarIcon: (tabInfo) => {
return <Ionicons name="ios-restaurant" size={25} color={tabInfo.tintColor} />
}
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'black',
}}
/>
<MealsFavTabNavigator.Screen
name="Favorites"
component={FavoritesScreen}
screenOptions={({ route }) => ({
tabBarIcon: (tabInfo) => {
return <Ionicons name="ios-star" size={25} color={tabInfo.tintColor} />
}
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'black',
}}
/>
</MealsFavTabNavigator.Navigator>
</NavigationContainer>
);
};
The icons doesnt work even the colors doesnt work and there are no errors on the console. Any idea what am I doing wrong?
The screenOptions prop is used for navigators not screens.
When using for screens you will have to use 'options' not screenOptions
<MealsFavTabNavigator.Screen
name="Favorites"
component={FavoritesScreen}
options={({ route }) => ({
tabBarIcon: (tabInfo) => {
return <Ionicons name="ios-star" size={25} color={tabInfo.tintColor} />
}
})}
/>
Also the tabBarOptions should be moved to navigator
<MealsFavTabNavigator.Navigator
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'black',
}}>