React Native Bottom Tab Navigator - Icons not displaying - react-native

/* eslint-disable react-native/no-inline-styles */
/* eslint-disable prettier/prettier */
import * as React from 'react';
import Home from '../screens/home';
import Review from '../screens/reviewDetails';
import Profile from '../screens/profile';
import Settings from '../screens/settings';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { COLORS, icons } from '../constants';
import { Image } from 'react-native';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
const Tab = createMaterialBottomTabNavigator();
export default function HomeStack() {
return (
<Tab.Navigator initialRouteName="Home">
<Tab.Screen name="Home" component={Home} options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="home" color={color} size={26} />
),
}} />
<Tab.Screen name="Review Details" component={Review} options={{
tabBarLabel: 'Review',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="home" color={color} size={26} />
),
}} />
<Tab.Screen name="Profile" component={Profile} options={{
tabBarLabel: 'Profile',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="home" color={color} size={26} />
),
}} />
<Tab.Screen name="Settings" component={Settings} options={{
tabBarLabel: 'Settings',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="home" color={color} size={26} />
),
}} />
</Tab.Navigator>
);
}
my code for a bottom tab navigator runs without any errors however when run in the emmulator the icons on the navigator do not display they are replaced by a crossed box? the tab navigator is also contained within a drawer content navigator which is in turn the child of a root stack navigator. all dependencies have been installed yet the error persists

Reading the documentation of the Tab.Navigator, you should define the icons inside of that. It would look like this:
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused
? 'ios-information-circle'
: 'ios-information-circle-outline';
} else if (route.name === 'Settings') {
iconName = focused ? 'ios-list-box' : 'ios-list';
}
// You can return any component that you like here!
return <MaterialCommunityIcons name={iconName} size={size} color={color} />;
},
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
This means you would be changing the component based on the route name. The reason behind it is that Tab.Screen should have information about the screen that will be displayed, while Tab.Navigator should handle the navigator (bottom strip with tabs) part of navigation.

Crossed box on android might come when the react-native-vector-icons is not link properly.
run this command
react-native link react-native-vector-icons
and in android/app/build.gradle file add this.
project.ext.vectoricons = [
iconFontNames: [ 'MaterialIcons.ttf' ] // Name of the font files you want to copy
]
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
I hope this will fix your crossed box issue.

return statement is missing in your code.
You can do it like this:
<Tab.Screen name="Review Details" component={Review} options={{
tabBarLabel: 'Review',
tabBarIcon: ({ color }) => (
return <MaterialCommunityIcons name="home" color={color} size={26} />
),
}} />
So update this line,
<MaterialCommunityIcons name="home" color={color} size={26} />
to this
return <MaterialCommunityIcons name="home" color={color} size={26} />

Related

React Native Tab Navigator

I am totally new to React Native and I am currently trying show BottomTabNavigator on child/details page, for example:
I have a page called Training and I have another page called TrainingDetails.
I wanna show BottomTabNavigator on TrainingDetails.
On truth, I wanna show BottomTabNavigator in all pages, main pages and detail pages.
Here is my Main.js
Thanks so much!
const Tab = createBottomTabNavigator();
return (
<Tab.Navigator tabBarOptions={{ activeTintColor: theme.colors.primary, inactiveTintColor: theme.colors.neutral_100, style: {backgroundColor: theme.colors.active} }}>
<Tab.Screen
options={{
title: "Trabalhar",
tabBarIcon: ({ focused, color, size }) => (
<MaterialIcon name={"headset"} size={size} color={color} />
),
}}
name="Home"
component={HomeScreen}
/>
<Tab.Screen
options={{
title: "Estudar",
tabBarIcon: ({ focused, color, size }) => (
<SimpleLineIcon name={"graduation"} size={size} color={color} />
),
}}
name="Study"
component={Training}
/>
<Tab.Screen
options={{
title: "Notificações",
tabBarIcon: ({ focused, color, size }) => (
<MaterialIcon name={"bell-outline"} size={size} color={color} />
),
}}
name="Notification"
component={HomeScreen}
/>
<Tab.Screen
options={{
title: "Resultados",
tabBarIcon: ({ focused, color, size }) => (
<MaterialIcon name={"trending-up"} size={size} color={color} />
),
}}
name="Results"
component={HomeScreen}
/>
<Tab.Screen
options={{
title: "Carteira",
tabBarIcon: ({ focused, color, size }) => (
<MaterialIcon name={"wallet-outline"} size={size} color={color} />
),
}}
name="Wallet"
component={HomeScreen}
/>
</Tab.Navigator>
);
};
export default Main;
You can put a stackNavigator inside a tab navigator, so for example if you want a home screen and then another screen called details that doesn't have a tab at the bottom but still has the tabs at the bottom you can replace the home screen with a homeStack that has both a home screen and details screen inside it.
const Stack = createStackNavigator();
function HomeStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Details" component={Details} />
</Stack.Navigator>
);
}
and then replace your home component in the tab navigator with HomeStack component.

How to keep track of screen title when bottom navigation is used in react native?

I am making use of bottom navigation in React Native and I have a header which is supposed to show on which screen I am at the moment. I am not sure how to change that text on Tab Bar press. I tried making use of onPress event but seems like it does not work.
Here is my code:
<View style={styles.container}>
<StatusBar barStyle="light-content" />
<View style={styles.header}>
<Text style={styles.headerText}>{headerText}</Text>
<SettingsIcon />
</View>
<View style={styles.main}>
<NavigationContainer >
<Tab.Navigator initialRouteName="Home" tabBarOptions={{
activeTintColor: '#FF9F0A',
inactiveTintColor:'white',
style: {
backgroundColor: '#000000',//color you want to change
}
}}>
<Tab.Screen name="Home" component={Home} options={{
tabBarLabel: 'HOME',
tabBarIcon: ({ color, size }) => (
<HomeTabIcon name="home" color={color} size={size} />
),
}}/>
<Tab.Screen name="Controls" component={Controls} options={{
tabBarLabel: 'CONTROLS',
tabBarIcon: ({ color, size }) => (
<ControlsTabIcon name="controls" color={color} size={size} />
),
}}/>
<Tab.Screen name="Charging" component={Charging} options={{
tabBarLabel: 'CHARGING',
tabBarIcon: ({ color, size }) => (
<ChargingTabIcon name="charging" color={color} size={size} />
),
}}/>
</Tab.Navigator>
</NavigationContainer>
</View>
</View>
you can nest your tab navigator in a screen navigator.
You can change the title of your screen navigator header in function of the name of your active screen.
for more information read this.
import React from 'react';
import { NavigationContainer, getFocusedRouteNameFromRoute } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const RootStack = createStackNavigator();
const Tab = createBottomTabNavigator();
function getHeaderTitle(route : any) {
// If the focused route is not found, we need to assume it's the initial screen
// This can happen during if there hasn't been any navigation inside the screen
// In our case, it's "Feed" as that's the first screen inside the navigator
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Home';
console.log("name route = ", routeName);
switch (routeName) {
case 'Home':
return 'name header tab1';
case 'tab1':
return 'name header tab1';
case 'tab2':
return 'name header tab2';
}
}
const HomeTabs = () => {
return (
<Tab.Navigator>
<Tab.Screen name="tab1" component={Component1} />
<Tab.Screen name="tab2" component={Component2} />
</Tab.Navigator>
);
};
function Root() {
return (
<NavigationContainer>
<RootStack.Navigator>
<RootStack.Screen
name="Home"
component={HomeTabs}
options={({ route }) => ({
headerTitle: getHeaderTitle(route),
})}
/>
</RootStack.Navigator>
</NavigationContainer>
);
};

React Native Vector Icons won't show in Bottom Tab Navigation in Android

the icon shows in a screen/page, but won't show in the bottom navigation. Solutions that I've tried:
Follow the installation guide from github, I've tried both the GRADLE & MANUAL options, but same result
Have tried to ./gradlew clean then npx react-native run-android, but same result
Have tried to npx react-native link react-native-vector-icons then npx react-native run-android, but same result
screenshot bottom nav bar
screenshot setting screen
It does appear in screen/page as shown in above screenshot, but won't show in the bottom navigation.
NOTE: I've tested both in emulator and real android device, but still got same result!
Code for the bottom tab
import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
import Ionicons from 'react-native-vector-icons/Ionicons'
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs'
import ProductNavigation from './ProductNavigation'
import SettingScreen from '../screen/SettingScreen'
const BottomTab = createBottomTabNavigator();
const BottomTabNav = () => {
return (
<BottomTab.Navigator>
<BottomTab.Screen
name="Home"
component={ProductNavigation}
options={{
tabBarLabel: "Home",
tabBarIcon:({color, size}) => {
<Ionicons name="home-outline" color={color} size={size} />
}}} />
<BottomTab.Screen
name="Settings"
component={SettingScreen}
options={{
tabBarLabel: "Settings",
tabBarIcon: ({color, size}) => {
<Ionicons name="settings-outline" color={color} size={size}
/>
}}} />
</BottomTab.Navigator>
)
}
export default BottomTabNav
const styles = StyleSheet.create({})
Also can you help why does the bottom tab goes to the next page?? where should I edit the code, thanks in advance. Below is the Screenshot:
The issue is very simple actually, you are not returning anything from the function,
tabBarIcon: ({color, size}) => {
//nothing returned here
<Ionicons name="settings-outline" color={color} size={size}
/>
You have to do this, either use brackets like below or use the return statement to your code.
tabBarIcon: ({color, size}) => (
<Ionicons name="settings-outline" color={color} size={size}
/>)
First, make sure you use the icons correctly.
For example, suppose we use MaterialCommunityIcons.
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator
initialRouteName="Home"
tabBarOptions={{
activeTintColor: '#e91e63',
}}
>
<Tab.Screen
name="Home"
component={Home}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Settings"
component={Settings}
options={{
tabBarLabel: 'Updates',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="settings" color={color} size={size} />
),
tabBarBadge: 3,
}}
/>
Tab.Navigator>
);
}
General usage is like this. Check the document for details. https://reactnavigation.org/docs/bottom-tab-navigator/
In my case I hadn't added
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
to the android/app/build.gradle as indicated in the [Oblador React Native Vector Icons README document][1]
[1]: https://github.com/oblador/react-native-vector-icons#android
Once I added that, my icons displayed.
You need to create a custom tab bar component, and add the icons there. React Navigation has a pretty good documentation - https://reactnavigation.org/docs/bottom-tab-navigator#tabbar

react navigation tab screen icon color props type

I use eslint with vs code for my react native project .
I created a bottom tabs navigation using react navigation v5 :
...
<Tab.Screen
name="Contacts"
component={ContactStackScreen}
options={{
tabBarLabel: 'Contacts',
tabBarColor: COLORS.DEFAULT,
tabBarIcon: ({color}) => (
<MaterialCommunityIcons name="contacts" color={color} size={26} />
),
}}
...
I got eslint error for color props :
'color' is missing in props validation
I tried to fix it :
ButtomTabs.propTypes = {
color: PropTypes.string,
};
but i got this error :
propType "color" is not required, but has no corresponding defaultProps declaration
I believe there's a misunderstanding by the previous answers as to what is causing eslint to throw the react/prop-types error in this case. The lint error is correct - what's missing is the props validation for the arrow function introduced for tabBarIcon. Since that arrow function returns a React component, eslint is correct in enforcing the react/prop-types rule. To satisfy the rule, you need to provide prop types for that arrow function (think of the arrow function as an anonymous component which takes color as a prop). Just add {color: string} as the type definition for the entire parameter of that arrow function like this:
({color}: {color: string}) =>
In context:
<Tab.Screen
name="Contacts"
component={ContactStackScreen}
options={{
tabBarLabel: 'Contacts',
tabBarColor: COLORS.DEFAULT,
tabBarIcon: ({color}: {color: string}) => (
<MaterialCommunityIcons name="contacts" color={color} size={26} />
),
}}
Ignore the warning. It's a false positive.
tabBarIcon isn't a component and propTypes are only applicable to components
You're adding propTypes on BottomTabs component, but the warning is likely from the eslint plugin assuming that the function passed to tabBarIcon is a component
As per the documentation,
tabBarIcon is a supported option in bottom tab navigator. So we know we can use it on our screen components in the options prop, but in this case chose to put it in the screenOptions prop of Tab.Navigator in order to centralize the icon configuration for convenience.
here is an example of using Icon with Tab.Screen
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator
initialRouteName="Feed"
tabBarOptions={{
activeTintColor: '#e91e63',
}}
>
<Tab.Screen
name="Feed"
component={Feed}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Notifications"
component={Notifications}
options={{
tabBarLabel: 'Updates',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="bell" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Profile"
component={Profile}
options={{
tabBarLabel: 'Profile',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="account" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
);
}

React Native Nested Navigation

import React from 'react';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
import {MaterialCommunityIcons,Feather} from '#expo/vector-icons';
import {VideoTab} from './VideoTab';
import {EbookTab} from './EbookTab';
import {TestTab} from './TestTab';
import {NotesTab} from './NotesTab';
const Bottom = createMaterialBottomTabNavigator();
export const BottomNav = ({navigation,route})=>{
return (
<Bottom.Navigator
initialRouteName="VideoTab"
activeColor="#1ca6d1"
inactiveColor="red"
labeled='true'
barStyle={{ backgroundColor: '#ffffff' }}
>
<Bottom.Screen
name="VideoTab"
component={VideoTab}
options={{
title:'Video',
tabBarLabel: 'Class',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="lightbulb-on-outline" color={color} size={26} />
),
}}
/>
<Bottom.Screen
name="NotesTab"
component={NotesTab}
options={{
title:'Notes',
tabBarLabel: 'Notes',
tabBarIcon: ({ color }) => (
<Feather name="book" color={color} size={26} />
),
}}
/>
<Bottom.Screen
name="EbookTab"
component={EbookTab}
options={{
tabBarBadge:true,
title:'Ebook',
tabBarLabel: 'QuestionBank',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="account" color={color} size={26} />
),
}}
/>
<Bottom.Screen
name="TestTab"
component={TestTab}
options={{
title:'Test',
tabBarLabel: 'Test',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="account" color={color} size={26} />
),
}}
/>
</Bottom.Navigator>
);
}
And this bottom navigation is inside a stack navigator.
Every screen name is a tab screen and every tab screen contain 3 tab.
When I am clicking any tab, then I want to change header title according to tab.
How to create this type of navigation header title in react native?
If you want to have every tab name to be the top try this: https://reactnavigation.org/docs/screen-options-resolution/
Check out the getHeaderTitle function and the switch statement below that - it helped me achieve this behavoir.