Getting error while implementing Tab Navigator in React Native - reactjs

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>
);
}

Related

Cannot render images in Tab Navigator under react navigation in React Native

/**
* 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]} />);}
}

Nested tab navigators don't work inside drawer navigator

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.

Label of createBottomTabNavigator not showing - React Native

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.

icons not showing on TabNavigator

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
}

Button not working for navigating to the other screen in react-native

I am using react-navigation and need by clicking the button sign in from welcomescreen move to signin page while its not working.
https://i.stack.imgur.com/w9vfX.png
Here is my code
1. app.js
StyleSheet, Text, View } from 'react-native';
import { TabNavigator, DrawerNavigator, StackNavigator } from 'react-navigation';
import WelcomeScreen from './screens/WelcomeScreen';
import SigninScreen from './screens/SigninScreen';
import SignupScreen from './screens/SignupScreen';
import HomeScreen from './screens/HomeScreen';
import BusinessScreen from './screens/BusinessScreen';
import TechScreen from './screens/TechScreen';
import EducationScreen from './screens/EducationScreen';
import LifestyleScreen from './screens/LifestyleScreen';
import ProfileScreen from './screens/ProfileScreen';
import FavoritesScreen from './screens/FavoritesScreen';
import SettingsScreen from './screens/SettingsScreen';
export default class App extends React.Component {
render() {
const MainNavigator = StackNavigator({
welcome: { screen: WelcomeScreen },
signin: { screen: SigninScreen },
signup: { screen: SignupScreen },
main: {
screen: DrawerNavigator({
home: { screen: HomeScreen },
business: { screen: BusinessScreen },
tech: { screen: TechScreen },
education: { screen: EducationScreen},
lifestyle: { screen: LifestyleScreen },
profile: {
screen: StackNavigator({
profile: { screen: ProfileScreen },
settings: { screen: SettingsScreen }
})
}
},
)
}
},)
return (
<MainNavigator />
);
}
}
2. WelcomeScreen
import React, { Component } from 'react';
import { View, Text} from 'react-native';
import Slides from '../components/Slides';
import PropTypes from 'prop-types';
const SLIDE_DATA = [
{ text: 'Welcome to JobApp', color: '#03A9F4' },
{ text: 'Use this to get a job', color: '#009688' },
{ text: 'Set your location, then swipe away', color: '#03A9F4' }
];
class WelcomeScreen extends Component {
render (){
onSlidesComplete = () => {
this.props.navigation.navigate('signin');
}
return (
<Slides data={SLIDE_DATA} onComplete={this.onSlidesComplete} />
);
}
}
export default WelcomeScreen;
3. Slide.js
import React, { Component } from 'react';
import { View, Text, ScrollView, Button, Dimensions } from 'react-native';
import PropTypes from 'prop-types';
const SCREEN_WIDTH = Dimensions.get('window').width;
class Slides extends Component {
renderLastSlide(index) {
if (index === this.props.data.length - 1) {
return (
<Button raised onPress={this.props.onComplete}
buttonStyle={styles.buttonStyle}
title="Sign In"
>
Sign In
</Button>
);
}
}
renderSlides() {
return this.props.data.map((slide, index) => {
return (
<View
key={slide.text}
style={[styles.slideStyle, { backgroundColor: slide.color }]}
>
<Text style={styles.textStyle}>{slide.text}</Text>
{this.renderLastSlide(index)}
</View>
);
});
}
render() {
return (
<ScrollView
horizontal
style={{ flex: 1 }}
pagingEnabled
>
{this.renderSlides()}
</ScrollView>
);
}
}
const styles = {
slideStyle: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
width: SCREEN_WIDTH
},
textStyle: {
fontSize: 30,
color: 'white'
},
buttonStyle: {
backgroundColor: '#0288D1',
marginTop: 15
}
};
export default Slides;
In WelcomeScreen if you are using arrow function like
onSlidesComplete = () => {
this.props.navigation.navigate('signin');
}
then you have to use the onPress like this.onSlidesComplete.bind(this) or if you are using the function like
onSlidesComplete() {
this.props.navigation.navigate('signin');
}
then you have to use the onPress like this.onSlidesComplete. In short replace the below code with your existing WelcomeScreen
import React, { Component } from 'react';
import { View, Text} from 'react-native';
import Slides from '../components/Slides';
import PropTypes from 'prop-types';
const SLIDE_DATA = [
{ text: 'Welcome to JobApp', color: '#03A9F4' },
{ text: 'Use this to get a job', color: '#009688' },
{ text: 'Set your location, then swipe away', color: '#03A9F4' }
];
class WelcomeScreen extends Component {
render (){
onSlidesComplete = () => {
this.props.navigation.navigate('signin');
}
return (
<Slides data={SLIDE_DATA} onComplete={this.onSlidesComplete.bind(this)} />
);
}
}
export default WelcomeScreen;

Resources