So I pulled one of my react native projects from a few months ago and While using it I discovered that TabNavigator was deprecated. So instread I am now using createBottomTabNavigator like they suggested. It seems to work out of the box, but for some reason my labels are not showing, only the icons in the tabs.
I was looking at the docs and it was saying it is actually default true for showing the label. For some reason the label just won't show up. Also tried to set the showLabel to true but that didn't do anything else. Someone with the same problem that got a fix?
My code
import React from 'react';
import { Text, View, Button, StyleSheet } from 'react-native';
// Icons for tabs
import I from 'react-native-vector-icons/MaterialCommunityIcons';
// Navigation dep
import { createBottomTabNavigator, createStackNavigator } from 'react-navigation';
// Custom components/screens
import HomeScreen from './screens/HomeScreen'
import FavoritesScreen from './screens/FavoritesScreen'
import AccountScreen from './screens/AccountScreen'
// Custom styles
import HeaderBar from './styles/HeaderBar'
// Tabs navigation
const HomeStack = createStackNavigator({
Home: HomeScreen
});
const FavoritesStack = createStackNavigator({
Favorites: FavoritesScreen
});
const AccountStack = createStackNavigator({
Account: AccountScreen
});
export default createBottomTabNavigator(
{
Home: HomeStack,
Favorites: FavoritesStack,
Account: AccountStack,
},
{
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Home') {
iconName = `tag${focused ? '' : '-outline'}`;
} else if (routeName === 'Favorites') {
iconName = `heart${focused ? '' : '-outline'}`;
} else {
iconName = `account-box${focused ? '' : '-outline'}`;
}
return <I name={iconName} size={25} color={tintColor} />;
},
tabBarLabel: () => {
const { routeName } = navigation.state;
return routeName.toUpperCase();
}
}),
tabBarOptions: {
activeTintColor: '#E95736',
inactiveTintColor: 'gray',
labelStyle: {
fontSize: 9,
fontFamily: 'Rubik-Medium'
},
style: {
backgroundColor: '#FAF8F8',
borderTopWidth: 0.5
},
},
}
);
I think the issue is related to tabBarLabel and I believe the problem will fix itself if you remove that bit. You can easily achieve the same effect by just making the label text upper case where you declare the route.
Related
Trying to create a BottomTabNavigtor in a React Native Application. This is my Navigator Code.
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { Platform } from "react-native";
import CategoriesScreen from "../screens/CategoriesScreen";
import CategoryMealScreen from "../screens/CategoryMealScreen";
import MealDetailScreen from "../screens/MealDetailScreen";
import FavoritesScreen from "../screens/FavoritesScreen";
import Colors from "../constants/colors";
const MealsNavigator = createStackNavigator(
{
Categories: {
screen: CategoriesScreen,
navigationOptions: {
title: "Meal Categories"
}
},
CategoryMeals: {
screen: CategoryMealScreen
}, MealDetail: MealDetailScreen
},
{
defaultNavigationOptions: {
headerStyle: {
backgroundColor: Platform.OS === 'android' ? Colors.primaryColor : ''
},
headerTintColor: Platform.OS === 'android' ? 'white' : Colors.primaryColor
},
}
);
const MealsFavTabNavigator = createBottomTabNavigator({
Meals: MealsNavigator,
Favorites: FavoritesScreen
});
export default createAppContainer(MealsFavTabNavigator);
Following a course for this application. Getting this error:
TypeError: (0, _native.createNavigatorFactory) is not a function.
(In '(0, _native.createNavigatorFactory)(BottomTabNavigator)',
'(0, _native.createNavigatorFactory)' is undefined)
Any Help would be appreciated. Thanks.
Well if you're using latest release of react-navigation, lots of things have changed:
https://reactnavigation.org/docs/en/bottom-tab-navigator.html
Now you have to use this syntax :
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
);
}
/**
* Author: Rahul Shetty
* Date: 10/10/2019
*
* Configure app routes
* #flow
*/
import React from 'react';
import { Image, StyleSheet } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { Recipes, Restaurants } from 'containers/root';
import FeedIcon from 'assets/icons/feed/icons-feed.png';
import RestaurantIcon from 'assets/icons/restaurant/icons-restaurant.png';
import routes from './routes';
type Screens = {
[string]: React$Node,
};
const styles = StyleSheet.create({
iconStyle: { width: 28, height: 28 },
});
const { RECIPES, RESTAURANTS } = routes;
const IMAGE_PATH = {
[RECIPES]: FeedIcon,
[RESTAURANTS]: RestaurantIcon,
};
// Common navigation options for stack navigator
const commonNavOptions = {
defaultNavigationOptions: {
gesturesEnabled: false,
drawerLockMode: 'locked-closed',
},
headerMode: 'none',
};
const TabBarComponent = ({ navigation, tintColor }) => {
const { routeName } = navigation.state;
// You can return any component that you like here!
return <Image style={styles.iconStyle} source={IMAGE_PATH[routeName]} />;
};
// A function that returns a stack of navigation screens on providing the Object of screen and it's path name
const StackNav = (screens: Screens) =>
createStackNavigator(screens, commonNavOptions);
// Screens for Recipes
const RecipeStack = StackNav({ [RECIPES]: Recipes });
// Screens for Restaurants
const RestaurantStack = StackNav({ [RESTAURANTS]: Restaurants });
// Tab container
const Root = createAppContainer(
createBottomTabNavigator(
{
RECIPE: RecipeStack,
RESTAURANT: RestaurantStack,
},
{
defaultNavigationOptions: ({ navigation }) => ({
tabBarComponent: ({ tintColor }) => (
<TabBarComponent tintColor={tintColor} navigation={navigation} />
),
}),
tabBarOptions: {
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
showIcon: true,
},
},
),
);
export default Root;
I am not sure what am I doing wrong. I tried digging through the official documentation. I couldn't find anything worth resolving this issue.
Define navigationOptions with the tabBarIcon inside.
You can return the image via the tabBarIcon.
The tabBarIcon receives a function with the several arguments and returns a component. In your case, an Image.
Try this in your tab container.
tabBarIcon: ({ tintColor }) => {
return (<Image style={styles.iconStyle} source={IMAGE_PATH[routeName]} />);}
}
I'm trying to embed tab navigators within a drawer navigator, but the drawer navigator sometimes stops working. Code: https://github.com/myplaceonline/testreactexpo/tree/drawernestedtabs
To reproduce the problem:
Click the Screen2 tab at the bottom
Open the drawer
Click Home
Open the drawer
Click Screen2
Nothing happens
Is there a better way to do this and keep the drawer and bottom tabs synchronized and avoid the issue where the drawer stops working?
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import {
createAppContainer,
createBottomTabNavigator,
createDrawerNavigator,
createStackNavigator,
NavigationActions,
DrawerActions,
} from 'react-navigation';
import { Ionicons } from '#expo/vector-icons';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#ffffff",
alignItems: "center",
justifyContent: "center",
},
});
class HomeScreen extends React.Component {
static navigationOptions = {
title: "Home",
};
render() {
return (
<View style={styles.container}>
<Text>Home</Text>
</View>
);
}
}
class Screen2Screen extends React.Component {
static navigationOptions = {
title: "Screen2",
};
render() {
return (
<View style={styles.container}>
<Text>Screen2</Text>
</View>
);
}
}
const AppScreensTabs = {
Home: HomeScreen,
Screen2: Screen2Screen,
};
const AppScreensTabOptions = {
tabBarOptions: {
showLabel: true,
},
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, horizontal, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
// https://expo.github.io/vector-icons/
if (routeName === "Home") {
iconName = "md-home";
} else if (routeName === "Screen2") {
iconName = "md-beer";
}
return <Ionicons name={iconName} size={25} color={tintColor} />;
},
}),
};
const AppScreens = {
TabHome: createBottomTabNavigator(
AppScreensTabs,
Object.assign(
{ initialRouteName: "Home" },
AppScreensTabOptions,
)
),
TabScreen2: createBottomTabNavigator(
AppScreensTabs,
Object.assign(
{ initialRouteName: "Screen2" },
AppScreensTabOptions,
)
),
};
const AppScreensStackNavigationOptions = {
defaultNavigationOptions: ({ navigation }) => ({
headerLeft: <Ionicons name="md-menu" size={25} onPress={ () => navigation.openDrawer() } style={{ marginLeft: 15 }} />
})
};
const AppDrawer = createAppContainer(createDrawerNavigator({
DrawerHome: {
screen: createStackNavigator(
AppScreens,
Object.assign(
{ initialRouteName: "TabHome" },
AppScreensStackNavigationOptions,
)
),
navigationOptions: {
drawerLabel: "Home",
}
},
DrawerScreen2: {
screen: createStackNavigator(
AppScreens,
Object.assign(
{ initialRouteName: "TabScreen2" },
AppScreensStackNavigationOptions,
)
),
navigationOptions: {
drawerLabel: "Screen2",
}
},
}));
export default class App extends React.Component {
render() {
return (
<AppDrawer />
);
}
}
<div data-snack-id="#git/github.com/myplaceonline/testreactexpo#drawernestedtabs" data-snack-platform="ios" data-snack-preview="true" data-snack-theme="light" style="overflow:hidden;background:#fafafa;border:1px solid rgba(0,0,0,.08);border-radius:4px;height:505px;width:100%"></div>
<script async src="https://snack.expo.io/embed.js"></script>
It seems you're trying to keep drawer state and tab state in sync, but I guess that from a UX perspective, it might make more sense to treat them as separate navigation containers, each with their own navigation hierarchy. Keeping them in sync is not straight-forward using react-navigation and is not a pattern I think people will be familiar with when navigation through your app.
I have been having some problems passing parameters from a screen in a switchNavigator to another in a TabNavigator
setvalue(response){
this.setState({profile :response})
console.warn(this.state.profile);
this.state.navigate('Navigators',{profile: profile})
}
The profile contains a JSON object of profile details. The navigation sends the date to the 'Navigators' screen which is just a TabNavigator
const Navigators = createAppContainer(Userstack);
export default RootStack = createSwitchNavigator(
{
Home: {
screen: Login
},
Register: {
screen: Registration
},
Navigators: {
screen: Navigators
},
},
{
initialRouteName: 'Home'
}
);
How the TabNavigator is created.
export default Userstack = createBottomTabNavigator(
{
User: {
screen: Profile
},
Discovery: {
screen: DiscoveryNavigator
},
},
{
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ tintColor }) => {
const { routeName } = navigation.state;
let IconComponent = Ionicons;
let iconName;
if (routeName === 'User') {
iconName = `md-contact`;
IconComponent = HomeIconWithBadge;
} else if (routeName === 'Discovery') {
iconName = `md-search`;
}
return <IconComponent name={iconName} size={27} color={tintColor} />;
},
}),
tabBarOptions: {
activeTintColor: '#00FA9A',
inactiveTintColor: 'black',
},
}
);
The screen I wish to access the profile information is
export default class Profile extends Component {
constructor(props){
super(props);
console.warn(props)
this.State = {
profile: this.props.navigation.params.profile
}
}
Did you try this.props.navigation.state.params?
According to Reference: https://reactnavigation.org/docs/params.html,
You can also directly access the params object with this.props.navigation.state.params. This may be null if no params were supplied, and so it's usually easier to just use getParam so you don't have to deal with that case.
Icon not showing in TabNavigator. My code:
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
import { StackNavigator,TabNavigator } from 'react-navigation';
import TestComp1 from './src/components/TestComp1'
import TestComp2 from './src/components/TestComp2'
import TestComp3 from './src/components/TestComp3'
import TestComp4 from './src/components/TestComp4'
import TestComp5 from './src/components/TestComp5'
export default class myApp extends Component {
render() {
return (
<MyApp />
);
}
}
const Tabs = TabNavigator({
TestComp3: {screen:TestComp3},
TestComp4: {
screen:TestComp4,
navigationOptions: ({ navigation }) => ({
title: "TestComp4",
tabBarIcon: ({ tintColor, focused }) => <View><MaterialIcons name="accessibility" size={20}/></View>
})
}
}, {
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: '#e91e63',
inactiveBackgroundColor: 'green', //This doesn't work
},
});
const MyApp = StackNavigator({
TestComp: {screen:TestComp1},
TestComp2: {screen:TestComp2},
Tabs: {
screen: Tabs
}
}, {
initialRouteName: "Tabs"
});
AppRegistry.registerComponent('MyApp', () => MyApp);
The label is showing for TestComp4 but the icon is not visible. How can I get the icon to show and change color on click?
The label is showing for TestComp4 but the icon is not visible. How can I get the icon to show and change color on click?
Found the problem, just set showIcon: true like so:
tabBarOptions: {
showIcon: true
}