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.
Related
So i have a bottom tab navigation into app.js with 3 tabs:
=> map
=> user
=> settings
<NavigationContainer>
<TabNav.Navigator initialRouteName='home'>
<TabNav.Screen name='home' component={Map} options={{
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="map-search-outline" color={color} size={30} style={style.iconStyle} />
), tabBarLabel: (null)
}} />
<TabNav.Screen name='user' component={User} options={{
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="card-account-details-outline" color={color} size={30} style={style.iconStyle} />
),tabBarLabel: (null)
}} />
<TabNav.Screen name='settings' component={Settings} options={{
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="set-square" color={color} size={30} style={style.iconStyle} />
), tabBarLabel: (null)
}} />
</TabNav.Navigator>
</NavigationContainer>
So I want to acces to a stack nav screen (report for exemple) anywhere into the children screens/components (a modal for exemple) of the map or the settings but not from the homescreen without showing it in the nav of the homescreen or the direct child of this homescreen, how can I do ?
In other words, I think I dont know where to write my hidden stack nav to be accessible from everywhere in the app. (but I understand how to pass it with the props)
I have a mobile app where i switch tabs from tab navigator
I want to add a debounce with useDebouncedCallback hook because I want to prevent user from clicking tabs constantly.
How can I add this to the navigator ? I tried with listeners prop (tabPress) and onPress on TabBarButton but doesn't work
// name={NAVIGATION.FRIENDS}
name="Friends"
component={Friends}
// listeners={{
// tabPress: e => {
// debouncedUpdate(() =>
// NavigationService.navigate(NAVIGATION.FRIENDS),
// );
// },
// }}
options={{
tabBarLabel: strings.tab.friend,
tabBarIcon: ({focused, color, size}) => (
<TabBarButton
routeName={strings.tab.friend}
focused={focused}
color={color}
onPress={debouncedUpdate(() =>
NavigationService.navigate(NAVIGATION.FRIENDS),
)}
/>
),
}}
/>
Below is the full Tab Navigator codes
import React from 'react';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import {TabBarButton} from '#/components/TabBarButton';
import Home from '#/screens/dashboard/home/Home';
import Friends from '#/screens/dashboard/friends/Friends';
import ChatThreads from '#/screens/dashboard/chat/chat_threads/ChatThreads';
import Profile from '#/screens/dashboard/profile/Profile';
import {
whiteColor,
primaryBgColor,
tabInactiveTintColor,
tabActiveTintColor,
} from '#/config/colors';
import {COMMON, NAVIGATION} from '#/constants';
import {strings} from '#/localization';
import {Host} from 'react-native-portalize';
import {useSelector} from 'react-redux';
import {useDebouncedCallback} from 'use-debounce';
const Tab = createBottomTabNavigator();
const TabNavigator = () => {
const newMessagesCount = useSelector(state => state.chat.newMessagesCount);
const debouncedUpdate = useDebouncedCallback(fn => {
fn();
}, 200);
return (
<>
<Host>
<Tab.Navigator
tabBarOptions={{
activeTintColor: tabActiveTintColor,
inactiveTintColor: tabInactiveTintColor,
showLabel: false,
style: {height: COMMON.BOTTOM_TAB_BAR_HEIGHT},
}}>
<Tab.Screen
name={NAVIGATION.HOME}
component={Home}
options={{
tabBarLabel: strings.tab.home,
tabBarIcon: ({focused, color, size}) => (
<TabBarButton
routeName={strings.tab.home}
focused={focused}
color={color}
/>
),
}}
/>
<Tab.Screen
name={NAVIGATION.FRIENDS}
component={Friends}
options={{
tabBarLabel: strings.tab.friend,
tabBarIcon: ({focused, color, size}) => (
<TabBarButton
routeName={strings.tab.friend}
focused={focused}
color={color}
/>
),
}}
/>
<Tab.Screen
name={NAVIGATION.CHAT_THREADS}
component={ChatThreads}
options={{
tabBarBadge:
newMessagesCount > 99 ? '99+' : String(newMessagesCount),
tabBarBadgeStyle: [
{
backgroundColor: primaryBgColor,
height: 20,
minWidth: 20,
borderRadius: 10,
color: whiteColor,
fontSize: 10,
left: 5,
opacity: newMessagesCount ? 1 : 0,
},
],
tabBarLabel: strings.tab.chat,
tabBarIcon: ({focused, color, size}) => (
<TabBarButton
routeName={strings.tab.chat}
focused={focused}
color={color}
/>
),
}}
/>
<Tab.Screen
name={NAVIGATION.PROFILE}
component={Profile}
options={{
tabBarLabel: strings.tab.profile,
tabBarIcon: ({focused, color, size}) => (
<TabBarButton
routeName={strings.tab.profile}
focused={focused}
color={color}
/>
),
}}
/>
</Tab.Navigator>
</Host>
</>
);
};
export default TabNavigator;
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.
/* 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} />
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>
);
}