icon in component header is not showing - react-native

I am following the doc example here to add a plus + to component header:
import React, { Component} from 'react';
import { SectionList, View, Image, StyleSheet, Text, TouchableOpacity, Platform, TouchableHighlight, AppRegistry } from 'react-native';
import {Icon } from "react-native-elements";
export default class Event extends React.Component {
static navigationOptions = ({navigation}) => {
console.log("in event header");
return {
headerTitle: 'Event',
headerRight: (
<TouchableOpacity>
<Icon
name="plus"
size={30}
type='octicon'
onPress={navigation.getParam('navToNewEvent')}
/>
</TouchableOpacity>
),
};
}
_navToNewEvent = () => {
console.log("Route to new event");
this.props.navigation.navigate("NewEvent");
};
async componentDidMount(){
this.props.navigation.setParams({ navToNewEvent: this._navToNewEvent })
....
}
However the plus + is not showing in component header:
What is missing in my code above?
UPDATE: the navigation code before component Event is:
return createBottomTabNavigator(
{
Event: {screen: EventStack},
Group: {screen: GroupStack},
Contact: {screen: ContactStack},
}, bottomTabNavOptions
);
const bottomTabNavOptions = {
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
console.log("route name", routeName);
let iconName;
if (routeName === 'Event') {
iconName = `list-unordered`;
} else if (routeName === 'NewEvent') {
iconName = "kebab-horizontal";
} else if (routeName === 'NewUser') {
iconName = `person`;
} else if (routeName === 'ListUser') {
iconName = `organization`
}
return <Icon name={iconName} size={30} color={tintColor} type='octicon' />;
},
}),
tabBarOptions: {
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
},
};
const EventStack = createStackNavigator({
Event: {
screen: EventWithSelf,
navigationOptions: {
title: 'Event',
},
},
NewEvent: {
screen: NeweventWithSelf,
navigationOptions: {
title: 'New Event',
},
},
EditEvent: {
screen: EditEventWithSelf,
navigationOptions: {
title: 'Edit Event',
},
},
Chat: {
screen: ChatWithSocket,
navigationOptions: {
title: 'Chat',
},
},
});

Simply looking at the code doesn't seem wrong. There is one catch. Would you like to modify this?
static navigationOptions = ({navigation}) => {
console.log("in event header");
return {
title: 'Event',
headerRight: (
<TouchableOpacity>
<Icon
name="plus"
size={30}
type='octicon'
onPress={() => navigation.getParam('navToNewEvent')}
/>
</TouchableOpacity>
),
};
}
You can use defaultNavigationOptions
The Event tab you represent is not a single screen. As a common header, configure the title and button in defaultNavigationOptions.
defaultNavigationOptions: ({ navigation }) => ({
...
headerTitle: 'Event',
headerRight: (
<TouchableOpacity>
<Icon
name="plus"
size={30}
type='octicon'
onPress={navigation.getParam('navToNewEvent')}
/>
</TouchableOpacity>
),

Related

Drawer does not open on first touch

I have a header that should open a drawer once it is touched. However the current behaviour is that it shows immediately the Profile screen (the drawer does not open) on first touch. If you touch the header again then the drawer is actually shown.
import ...
const navigationOptions = (navigation) => {
return {
title: navigation.screenProps.t('app.title')
}
}
const defaultNavigationOptionsWithHeader = ({ navigation }) => {
return {
headerStyle: {
backgroundColor: Colors.backgroundColor,
},
headerTintColor: Colors.main,
headerTitleStyle: {
fontWeight: 'bold'
},
headerRight: <TouchableOpacity style={{ marginRight: 10 }} onPress={() => navigation.dispatch(DrawerActions.openDrawer())}>
<Ionicons
name={Platform.OS === 'ios'
? 'ios-menu'
: 'md-menu'}
size={40}
color={Colors.main}
/>
</TouchableOpacity>
}
}
const defaultNavigationOptionsWithoutHeader = ({ navigation }) => {
return {
headerStyle: {
backgroundColor: Colors.backgroundColor,
},
headerTintColor: Colors.main,
headerTitleStyle: {
fontWeight: 'bold'
}
}
}
const AuthStack = createStackNavigator(
{
Login: {
screen: LoginScreen,
navigationOptions: navigationOptions
},
Registration: {
screen: RegistrationScreen,
navigationOptions: navigationOptions
}
}, {
initialRouteName: 'Login',
defaultNavigationOptions: defaultNavigationOptionsWithoutHeader
});
const TabStack = createStackNavigator(
{
App: {
screen: TabNavigator,
navigationOptions: navigationOptions
}
}, {
defaultNavigationOptions: defaultNavigationOptionsWithHeader
}
);
const MenuStack = createStackNavigator(
{
App: {
screen: MenuNavigator,
navigationOptions: navigationOptions
}
}, {
defaultNavigationOptions: defaultNavigationOptionsWithHeader
}
);
const appNavigationOptions = (navigation) => {
return {
initialRouteName: 'Tab'
}
}
const AppStack = createSwitchNavigator(
{
Tab: TabStack,
Menu: MenuStack
},
{
defaultNavigationOptions: appNavigationOptions
}
)
export default createAppContainer(createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
Auth: AuthStack,
App: AppStack
},
{
initialRouteName: 'AuthLoading',
}
));
Does anybody know what causes this issue? The menu navigator is defined as follows:
import ...
handleHome = (navigation) => {
navigation.navigate('App')
}
handleLogout = (navigation) => {
logout();
navigation.navigate('Auth')
}
const config = Platform.select({
web: { headerMode: 'screen' },
default: {},
});
const navigationOptions = (navigation) => {
return {
header: null
}
}
const ProfileStack = createStackNavigator(
{
Map: {
screen: ProfileScreen,
navigationOptions: navigationOptions
}
},
config
);
ProfileStack.navigationOptions = (navigation) => {
return {
drawerLabel: navigation.screenProps.t('loggedin.sidebar.profile'),
drawerIcon: ({ focused }) => (<DrawerIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-contact'}`
: 'md-contact'
}
/>)
};
}
ProfileStack.path = '';
const PreferencesStack = createStackNavigator(
{
Settings: {
screen: PreferencesScreen,
navigationOptions: navigationOptions
}
},
config
);
PreferencesStack.navigationOptions = (navigation) => {
return {
drawerLabel: navigation.screenProps.t('loggedin.sidebar.preferences'),
drawerIcon: ({ focused }) => (<DrawerIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-settings'}`
: 'md-settings'
}
/>)
}
};
const LogoutStack = createStackNavigator(
{
Logout: {
screen: () => null,
navigationOptions: navigationOptions
}
},
config
);
LogoutStack.navigationOptions = (navigation) => {
return {
drawerLabel: navigation.screenProps.t('button.logout'),
drawerIcon: ({ focused }) => createDrawerIcon('log-out', focused)
};
}
const TabStack = createStackNavigator(
{
Logout: {
screen: () => null,
navigationOptions: navigationOptions
}
},
config
);
TabStack.navigationOptions = (navigation) => {
return {
drawerLabel: navigation.screenProps.t('app.title'),
drawerIcon: ({ focused }) => createDrawerIcon('home', focused)
};
}
createDrawerIcon = (icon, focused = false) => {
return <DrawerIcon
focused={focused}
name={
Platform.OS === 'ios'
? 'ios-' + icon
: 'md-' + icon
}
/>
}
const MenuDrawerItem = (props) => {
return <TouchableOpacity onPress={props.onPress} >
<View style={styles.item}>
<View style={styles.iconContainer}>
{createDrawerIcon(props.icon)}
</View>
<Text style={styles.label}>{props.text}</Text>
</View>
</TouchableOpacity >
}
const MenuDrawer = (props) => (
<ScrollView contentContainerStyle={{ flex: 1, flexDirection: 'column', justifyContent: 'space-between' }}>
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<MenuDrawerItem onPress={() => this.handleHome(props.navigation)} text={props.screenProps.t('app.title')} icon={'home'} />
<DrawerItems {...props} />
</SafeAreaView>
<MenuDrawerItem onPress={() => this.handleLogout(props.navigation)} text={props.screenProps.t('button.logout')} icon={'log-out'} />
</ScrollView>
);
const menuNavigator = createDrawerNavigator({
ProfileStack,
PreferencesStack
}, {
drawerPosition: 'right',
contentComponent: props => <MenuDrawer {...props} />,
contentOptions: {
activeTintColor: Colors.main
},
initialRouteName: 'ProfileStack'
}
);
menuNavigator.path = ''
export default menuNavigator
const styles = ...
That's probably you might have something other in focus.
May be Keyboard, TextField, Or some other things which are in focus and when you click for the first time the focus gets removed and when you press for the second time the drawer gets opened.
Try calling an alert instead of opening the drawer on button press and then debug that. That will troubleshoot the issue

How to set navigationsOptions for two tabs and check the routeName to config the different iconNames?

I have created a bottom navigator with crateBottomNavigator. It has 2 tabs. The 1st is a Navigator, created with createStackNavigator. The 2d is a normal screen.
I use as a second arg the navigationOptions and in there the tabBarIcon, in order to get the routeName and give our tabs a different icon, according to: 1) the routeName and 2) if it is focused or not.
I followed the steps of React Navigation docs.
The problem is that the icons do not show up!
But, the tabs are functional.
// CODE WITH PROBLEM
const MealsFavTabNavigator = createBottomTabNavigator(
{
Meals: MealsNavigator,
Favorites: FavoritesScreen
},
{
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Meals') {
iconName = `restaurant${focused ? '' : '-menu'}`;
} else if (routeName === 'Favorites') {
iconName = `favorite${focused ? '' : '-border'}`;
}
return <MaterialIcons name={iconName} size={25} color={tintColor} />;
}
}),
tabBarOptions: {
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}
}
);
If I separate the screens then it works well.
// CODE WITH NO PROBLEM
const MealsFavTabNavigator = createBottomTabNavigator(
{
Meals: {
screen: MealsNavigator,
// navigationOptions in config of a navigator, only matter if that
// navigator is used inside of another navigator.
navigationOptions: {
tabBarIcon: ({ focused, tintColor }) => {
let iconName = `restaurant${focused ? '' : '-menu'}`;
return <MaterialIcons name={iconName} size={25} color={tintColor} />;
}
}
},
Favorites: {
screen: FavoritesScreen,
navigationOptions: {
tabBarLabel: 'Favorites!',
tabBarIcon: ({ focused, tintColor }) => {
let iconName = `favorite${focused ? '' : '-border'}`;
return <MaterialIcons name={iconName} size={25} color={tintColor} />;
}
}
}
},
{
tabBarOptions: {
activeTintColor: Colors.active,
inactiveColor: Colors.inactive
}
}
);
Here is the whole module.
import React from 'react';
import { createStackNavigator, createAppContainer } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { Platform } from 'react-native';
import { MaterialIcons } 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 Colors from '../constants/Colors';
const MealsNavigator = createStackNavigator(
{
Categories: {
screen: CategoriesScreen
},
CategoryMeals: {
screen: CategoryMealsScreen
},
MealDetail: MealDetailScreen
},
{
defaultNavigationOptions: {
headerStyle: {
backgroundColor: Platform.OS === 'android' ? Colors.primaryColor : ''
},
headerTintColor: Platform.OS === 'android' ? 'white' : Colors.primaryColor,
headerTitle: 'A Screen'
}
}
);
const MealsFavTabNavigator = createBottomTabNavigator(
{
Meals: MealsNavigator,
Favorites: FavoritesScreen
},
{
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Meals') {
iconName = `restaurant${focused ? '' : '-menu'}`;
} else if (routeName === 'Favorites') {
iconName = `favorite${focused ? '' : '-border'}`;
}
return <MaterialIcons name={iconName} size={25} color={tintColor} />;
}
}),
tabBarOptions: {
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}
}
);
export default createAppContainer(MealsFavTabNavigator);
Thanks :)
As we figured it out through the comments, I'll write it as definitive answer here.
The problem is that navigationOptions, as parameter in createBottomTabNavigator, doesn't have a tabBarIcon key usable to specify a specific tab icon.
To do that, you need to pass it as parameter inside defaultNavigationOptions, used to specify standard options for every item of the navigator, such as tabBarIcon.
Further, I wanted to change the icons and the color, but the icons where all from different sets.
This is with what I finally came up.
defaultNavigationOptions: ({ navigation }) => ({
// Ionicons = ios-book
// MaterialCommunityIcons = book
// FontAwesome = cross
// FontAwesome5 = bolnisi-cross
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName = '';
if (routeName === 'Books') {
iconName = focused ? 'ios-book' : 'book';
} else if (routeName === 'Favorites') {
iconName = focused ? 'bolnisi-cross' : 'cross';
}
// For Books
if (routeName === 'Books' && focused) {
return <Ionicons name={iconName} size={25} color={tintColor} />;
// For Favorites
} else if (routeName === 'Favorites' && focused) {
return <MaterialCommunityIcons name={iconName} size={25} color={tintColor} />;
}
// For Books
if (routeName === 'Books' && !focused) {
return <FontAwesome name={iconName} size={25} color={tintColor} />;
// For Favorites
} else if (routeName === 'Favorites' && !focused) {
return <FontAwesome5 name={iconName} size={25} color={tintColor} />;
}
}
}),

Remove the navigation header from the react-native screen - stack navigation

I have a screen which has tab-bar navigation where each screen is of type stack navigation with a couple of screens defined in each. When I navigate from FamilyMembers to SingleContact screen I don't want to see the navigation bar with the back button on top. I want my view (the blue one) in single contact to start from the top. But it appears although I set the header to null! Please help.
//------------------- Single Contact Screen----------//
import { Text, AsyncStorage, Image, FlatList, Alert, ActivityIndicator, Platform, StyleSheet, View } from 'react-native';
import { Icon, Container, Spinner, Content, Left, Right, Header, ListItem } from 'native-base'
import profileService from '../services/Api/ProfileService';
import { SafeAreaView } from 'react-navigation';
HEADER_MAX_HEIGHT = 100
HEADER_MIN_HEIGHT = 60
PROFILE_IMAGE_MAX_HEIGHT = 80
PROFILE_IMAGE_MIN_HEIGHT = 40
export default class SingleContact extends Component {
constructor(props) {
super(props);
this.state = { userName: "", contacts: [], userID: "", cookie: null, memberShips: [] };
}
async componentDidMount() {
}
onDataLoaded(result, userName) {
}
render() {
return (
<SafeAreaView>
<View style={{ flex: 1 }}>
//--------------------App.js navigation setup --------------------------//
const FamilyMembersStack = createStackNavigator({
FamilyMembers: {
screen: FamilyMembers,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Family members",
}
}
},
SingleContact: {
screen: SingleContact,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Contact"
}
}
},
}
, {
mode: 'modal',
headerMode: 'none'
});
const HomeScreenStack = createStackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
},
FamilyMembersStack: {
screen: FamilyMembersStack,
navigationOptions: ({ navigation }) => {
return {
header: null
}
}
},
AttendanceHistory: {
screen: AttendanceHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Attendance history"
}
}
},
OrderHistory: {
screen: OrderHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Order history"
}
}
}
});
HomeScreenStack.navigationOptions = {
tabBarLabel: 'My info',
tabBarIcon: ({ tintColor }) => (
<FaIcon name="user" size={20} color={tintColor} />
),
};
const ScheduleScreenStack = createStackNavigator({
Schedule: {
screen: ScheduleScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
}
});
ScheduleScreenStack.navigationOptions = {
tabBarLabel: 'Find a class',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-calendar" size={20} color={tintColor} />
),
};
const ShopScreenStack = createStackNavigator({
Shop: {
screen: ShopScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
}
});
ShopScreenStack.navigationOptions = {
tabBarLabel: 'Get a pass',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-basket" size={20} color={tintColor} />
),
};
const NotificationsScreenStack = createStackNavigator({
Notifications: {
screen: NotificationsScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
}
});
NotificationsScreenStack.navigationOptions = {
tabBarLabel: 'Notifications',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-alert" size={20} color={tintColor} />
),
};
const EventsStack = createStackNavigator({
Events: {
screen: Events,
navigationOptions: ({ navigation }) => {
return {
tabBarLabel: "Events",
tabBarIcon: ({ tintColor }) => (
<Icon name="md-calendar" size={20} />
),
headerLeft: (
<Icon name="md-menu" style={{ paddingLeft: 10 }}
onPress={() => navigation.openDrawer()}
size={30} />
)
}
}
}
});
EventsStack.navigationOptions = {
tabBarLabel: 'Events',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-calendar" size={20} color={tintColor} />
),
};
const DashboardTabNavigator = createBottomTabNavigator({
HomeScreenStack,
ScheduleScreenStack,
ShopScreenStack,
NotificationsScreenStack
},
{
navigationOptions: ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
return {
header: null,
headerTitle: routeName,
}
},
tabBarOptions: {
activeTintColor: 'white',
inactiveTintColor: 'silver',
labelStyle: {
fontSize: 12,
},
style: {
backgroundColor: 'rgba(24,130,201,1);',
},
}
}, { initialRouteName: HomeScreenStack }
);
const DashboardStackNavigator = createStackNavigator({
DashboardTabNavigator: DashboardTabNavigator
});
const AppDrawerNavigator = createDrawerNavigator({
Dashboard: {
screen: DashboardStackNavigator
}
}, {
contentComponent: props => <DrawerContent {...props} />
});
const AppSwitchNavigator = createSwitchNavigator({
AuthLoading: AuthLoadingScreen,
Login: { screen: Login },
Dashboard: { screen: AppDrawerNavigator }
}, {
initialRouteName: 'AuthLoading',
}
);
const AppContainer = createAppContainer(AppSwitchNavigator);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
Did you already modify your FamilyMembersStack inside HomeScreenStack like this?
const HomeScreenStack = createStackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
},
// modify this Stack
FamilyMembersStack:{
screen: FamilyMembersStack,
navigationOptions: ({ navigation }) => {
return {
header: null
}
}
}
AttendanceHistory: {
screen: AttendanceHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Attendance history"
}
}
},
OrderHistory: {
screen: OrderHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Order history"
}
}
}
});
Follow up answer, remove the following. so that the header will render on the designated screen:
export default class SingleContact extends Component {
static navigationOptions = {
header: null, // remove this
}
constructor(props) {
super(props);
this.state = { userName: "", contacts: [], userID: "", cookie: null, memberShips: [] };
}
async componentDidMount() {
}
onDataLoaded(result, userName) {
}
render() {
//------------------------------//
const FamilyMembersStack = createStackNavigator({
FamilyMembers: {
screen: FamilyMembers,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Family members",
header:null
}
}
},
SingleContact: {
screen: SingleContact,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Contact",
header:null // and remove this
}
}
},
});

Navigating to a new view

How to correctly navigate to a new view?
App:
TabNavigator (Top of the screen)
StackNavigator (Bottom of the screen)
I want that after choosing a button from StackNavigator opened a new screen that will override the entire application. I do not want to see TabNavigator and StackNavigator.
In the new window, I want it to be NavBar with the return button
All the tutorials that I'm watching show how to switch between screens but I can not find the situation above.
I want to open a new window from the main application and then return to it
EDITED:
const TopNavTabs = TabNavigator({
General: { screen: General },
Help: { screen: Help },
Tips: { screen: Tips },
}
});
export const Navigation = StackNavigator(
{
Tab: { screen: TopNavTabs },
Article: { screen: Article },
}
);
export default class App extends Component{
render(){
return(
<View>
<View>
<Navigation navigation={this.props.navigation} />
</View>
<View>
<View>
<MCIcon name="account"/>
</View>
<View>
<MIcon name="create" onPress={() => this.props.navigation.navigate('Article')} />
</View>
<View>
<FAIcon name="hashtag" />
</View>
<View>
<FAIcon name="search" />
</View>
</View>
</View>
)
}
}
Add TabNavigator in StackNavigator like:
const TopNavTabs = TabNavigator(
{
General: { screen: General },
Help: { screen: Help },
Tips: { screen: Tips },
},
{
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Home') {
iconName = `ios-information-circle${focused ? '' : '-outline'}`;
} else if (routeName === 'Settings') {
iconName = `ios-options${focused ? '' : '-outline'}`;
}
// You can return any component that you like here! We usually use an
// icon component from react-native-vector-icons
return <Ionicons name={iconName} size={25} color={tintColor} />;
},
}),
tabBarOptions: {
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
},
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false,
}
);
export const Navigation = StackNavigator(
{
Tab: { screen: TopNavTabs },
Article: { screen: Article },
}
);
export default class App extends Component{
render(){
return(
<Navigation />
)
}
}

React Native component life cycle - which function gets called when screen is visible

I've been looking at the documentation here https://reactjs.org/docs/react-component.html, but there is something that keeps bugging me. A pattern which I almost constantly seem to need but I am unable to find a solution to it and so always have to find hacks around it.
The pattern that I'm talking about is as follows. My app has a TabNavigator and I understand that when the app gets initialised ComponentDidMount is called on all the tabs. What I would like are functions that get called when a Tab is either navigated to, using this.props.navigation.navigate('TAB1') or when the tab is clicked at the bottom of the screen.
If someone can help with this I'd really appreciate it. Apologies there is no code to show for this.
Thanks
First, to understand the reason why it's not so easy, read the following conversation in the corresponding issue: https://github.com/react-navigation/react-navigation/issues/51
Here is what currently looks like the most effective solution: https://github.com/react-navigation/react-navigation/pull/3345
And this is the example code you can try out:
import type {
NavigationScreenProp,
NavigationEventSubscription,
} from 'react-navigation';
import React from 'react';
import { Button, Platform, ScrollView, StatusBar, View } from 'react-native';
import { SafeAreaView, TabNavigator } from 'react-navigation';
import Ionicons from 'react-native-vector-icons/Ionicons';
import SampleText from './SampleText';
const MyNavScreen = ({ navigation, banner }) => (
<SafeAreaView forceInset={{ horizontal: 'always', top: 'always' }}>
<SampleText>{banner}</SampleText>
<Button
onPress={() => navigation.navigate('Home')}
title="Go to home tab"
/>
<Button
onPress={() => navigation.navigate('Settings')}
title="Go to settings tab"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
<StatusBar barStyle="default" />
</SafeAreaView>
);
const MyHomeScreen = ({ navigation }) => (
<MyNavScreen banner="Home Tab" navigation={navigation} />
);
MyHomeScreen.navigationOptions = {
tabBarTestIDProps: {
testID: 'TEST_ID_HOME',
accessibilityLabel: 'TEST_ID_HOME_ACLBL',
},
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-home' : 'ios-home-outline'}
size={26}
style={{ color: tintColor }}
/>
),
};
type MyPeopleScreenProps = {
navigation: NavigationScreenProp<*>,
};
class MyPeopleScreen extends React.Component<MyPeopleScreenProps> {
_s0: NavigationEventSubscription;
_s1: NavigationEventSubscription;
_s2: NavigationEventSubscription;
_s3: NavigationEventSubscription;
static navigationOptions = {
tabBarLabel: 'People',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-people' : 'ios-people-outline'}
size={26}
style={{ color: tintColor }}
/>
),
};
componentDidMount() {
this._s0 = this.props.navigation.addListener('willFocus', this._onEvent);
this._s1 = this.props.navigation.addListener('didFocus', this._onEvent);
this._s2 = this.props.navigation.addListener('willBlur', this._onEvent);
this._s3 = this.props.navigation.addListener('didBlur', this._onEvent);
}
componentWillUnmount() {
this._s0.remove();
this._s1.remove();
this._s2.remove();
this._s3.remove();
}
_onEvent = a => {
console.log('EVENT ON PEOPLE TAB', a.type, a);
};
render() {
const { navigation } = this.props;
return <MyNavScreen banner="People Tab" navigation={navigation} />;
}
}
type MyChatScreenProps = {
navigation: NavigationScreenProp<*>,
};
class MyChatScreen extends React.Component<MyChatScreenProps> {
_s0: NavigationEventSubscription;
_s1: NavigationEventSubscription;
_s2: NavigationEventSubscription;
_s3: NavigationEventSubscription;
static navigationOptions = {
tabBarLabel: 'Chat',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-chatboxes' : 'ios-chatboxes-outline'}
size={26}
style={{ color: tintColor }}
/>
),
};
componentDidMount() {
this._s0 = this.props.navigation.addListener('willFocus', this._onEvent);
this._s1 = this.props.navigation.addListener('didFocus', this._onEvent);
this._s2 = this.props.navigation.addListener('willBlur', this._onEvent);
this._s3 = this.props.navigation.addListener('didBlur', this._onEvent);
}
componentWillUnmount() {
this._s0.remove();
this._s1.remove();
this._s2.remove();
this._s3.remove();
}
_onEvent = a => {
console.log('EVENT ON CHAT TAB', a.type, a);
};
render() {
const { navigation } = this.props;
return <MyNavScreen banner="Chat Tab" navigation={navigation} />;
}
}
const MySettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Settings Tab" navigation={navigation} />
);
MySettingsScreen.navigationOptions = {
tabBarLabel: 'Settings',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-settings' : 'ios-settings-outline'}
size={26}
style={{ color: tintColor }}
/>
),
};
const SimpleTabs = TabNavigator(
{
Home: {
screen: MyHomeScreen,
path: '',
},
People: {
screen: MyPeopleScreen,
path: 'cart',
},
Chat: {
screen: MyChatScreen,
path: 'chat',
},
Settings: {
screen: MySettingsScreen,
path: 'settings',
},
},
{
lazy: true,
removeClippedSubviews: true,
tabBarOptions: {
activeTintColor: Platform.OS === 'ios' ? '#e91e63' : '#fff',
},
}
);
type SimpleTabsContainerProps = {
navigation: NavigationScreenProp<*>,
};
class SimpleTabsContainer extends React.Component<SimpleTabsContainerProps> {
static router = SimpleTabs.router;
_s0: NavigationEventSubscription;
_s1: NavigationEventSubscription;
_s2: NavigationEventSubscription;
_s3: NavigationEventSubscription;
componentDidMount() {
this._s0 = this.props.navigation.addListener('willFocus', this._onAction);
this._s1 = this.props.navigation.addListener('didFocus', this._onAction);
this._s2 = this.props.navigation.addListener('willBlur', this._onAction);
this._s3 = this.props.navigation.addListener('didBlur', this._onAction);
}
componentWillUnmount() {
this._s0.remove();
this._s1.remove();
this._s2.remove();
this._s3.remove();
}
_onAction = a => {
console.log('TABS EVENT', a.type, a);
};
render() {
return <SimpleTabs navigation={this.props.navigation} />;
}
}
export default SimpleTabsContainer;
For the source and other codes, look here: https://github.com/react-navigation/react-navigation/blob/master/examples/NavigationPlayground/js/SimpleTabs.js