I want to reload the tabNavigator when the user changse the tab each time. the lifecycle method of react native doesn't get called when user changes the tab. Then how can it be possible to reload tab in TabNavigator :
The below example have two Tabs : 1) Home 2)Events. Now I want to refresh the event Tab when user returns from the home tab.
EXPO LINK : Expo Tab Navigator
Code :
import React, {Component} from 'react';
import {View, StyleSheet, Image, FlatList, ScrollView, Dimensions } from 'react-native';
import { Button, List, ListItem, Card } from 'react-native-elements' // 0.15.0
//import { Constants } from 'expo';
import { TabNavigator, StackNavigator } from 'react-navigation'; // 1.0.0-beta.11
//image screen width and height defs
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;
export default class App extends Component {
render() {
//const { navigate } = this.props.navigation;
return (
<TabsNav />
)
}
}
class MyHomeScreen extends Component {
render() {
return (
<View>
<Image
resizeMode="cover"
style={{ width: windowWidth * .85, height: windowHeight * 0.3}}
source={{uri: 'http://www.ajaxlibrary.ca/sites/default/files/media/logo.png?s358127d1501607090'}}
/>
<Button
onPress={() => this.props.navigation.navigate('Notifications')}
title="Go to notifications"
/>
</View>
);
}
}
class AplEvents extends Component {
static navigationOptions = {
tabBarLabel: 'Events List',
tabBarIcon: ({ tintColor }) => (
<Image
source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
constructor(props) {
super(props);
this.state = {
data: [],
error: null,
};
}
// when component mounts run the function fetch
componentDidMount() {
this.makeRemoteRequest();
}
makeRemoteRequest = () => {
const url = `http://www.ajaxlibrary.ca/?q=calendar-test`;
fetch(url)
.then((res) => res.json())
.then((res) => {
this.setState({
data: [...this.state.data, ...res.nodes],
error: res.error || null,
});
})
.catch(error => {
this.setState( error );
});
};
render() {
const { navigate } = this.props.navigation;
return (
<List containerStyle={{ marginTop: 0, borderTopWidth: 0, borderBottomWidth: 0 }}>
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<ListItem
//squareAvatar
title={`${item.node.title}\n${item.node.Program_Location}`}
subtitle={item.node.Next_Session}
avatar={{ uri: item.node.Image }}
containerStyle={{ borderBottomWidth: 0 }}
// save params to pass to detailed events screen
onPress={() => navigate('Details', {title: `${item.node.title}`,
body: `${item.node.Body}`,
date: `${item.node.Date}`,
Next_Session: `${item.node.Next_Session}`,
Program_Location: `${item.node.Program_Location}`,
Nid: `${item.node.Nid}`,
Image: `${item.node.Image}`,
Run_Time: `${item.node.Run_Time}`})}
/>
)}
keyExtractor={item => item.node.Nid}
/>
</List>
);
}
}
class EventDetails extends Component {
static navigationOptions = {
title: 'EventDetails'
};
render() {
const { params } = this.props.navigation.state;
let pic = {
uri: `${params.Image}`
};
//const pic = { params.Image };
return (
<ScrollView>
<Card
title={params.title}
>
<Image
resizeMode="cover"
style={{ width: windowWidth * .85, height: windowHeight * 0.3}}
source={pic}
/>
<Button style={{marginTop: 10}}
icon={{name: 'date-range'}}
backgroundColor='#03A9F4'
fontFamily='Lato'
buttonStyle={{borderRadius: 0, marginLeft: 0, marginRight: 0, marginBottom: 0}}
title='Add to Calendar'
/>
<ListItem
title="Event Description"
subtitle={params.body}
hideChevron='true'
/>
<ListItem
title="Date"
subtitle={`${params.Next_Session}\n Run Time - ${params.Run_Time}`}
hideChevron='true'
/>
<ListItem
title="Location"
subtitle={params.Program_Location}
hideChevron='true'
/>
</Card>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 26,
height: 26,
},
});
const EventStack = StackNavigator({
EventList: {
screen: AplEvents,
navigationOptions: {
title: "APL Event Listing",
}
},
Details: {
screen: EventDetails,
},
TabsNav: { screen: MyHomeScreen}
});
const TabsNav = TabNavigator({
Home: {
screen: MyHomeScreen,
navigationOptions: {
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor }) => (
<Image
source={{uri: 'https://upload.wikimedia.org/wikipedia/de/thumb/9/9f/Twitter_bird_logo_2012.svg/154px-Twitter_bird_logo_2012.svg.png'}}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
},
},
EventList: {
screen: EventStack,
navigationOptions: {
tabBarLabel: 'Events',
tabBarIcon: ({ tintColor }) => (
<Image
source={{uri: 'https://upload.wikimedia.org/wikipedia/de/thumb/9/9f/Twitter_bird_logo_2012.svg/154px-Twitter_bird_logo_2012.svg.png'}}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
},
},
}, {
tabBarOptions: {
activeTintColor: '#e91e63',
},
});
React Native Tab Navigation has an option prop as unmountOnBlur set it to true and it will reload the tab screens every time you click on tabs.
<Tab.Screen name={"Profile"} component={ProfileScreen} options={{unmountOnBlur: true}} />
Doc/Ref - RN Bottom tab Navigator docs
.
Update - There is a hook called as useIsFocused in '#react-navigation/native'.
Use this with useEffect to re-render the screen every time it is focused or used .
import { useIsFocused } from '#react-navigation/native';
const isFocused = useIsFocused();
useEffect(() => { yourApiCall(); }, [isFocused])
look at this link. My problem is solving thanks to this.
<Tabs.Navigator
initialRouteName="Home"
tabBar={(props) => (
<TabBar {...props} />
)}>
<Tabs.Screen
name="Home"
component={HomeView}
options={{ unmountOnBlur: true }}
listeners={({ navigation }) => ({
blur: () => navigation.setParams({ screen: undefined }),
})}
/>
</Tabs.Navigator>
https://github.com/react-navigation/react-navigation/issues/6915#issuecomment-692761324
There's many long discussion about this from react-native issue 314, 486, 1335, and finally we got a way to handle this, after Sep 27, 2017, react-navigation version v1.0.0-beta.13:
New Features
Accept a tabBarOnPress param (#1335) - #cooperka
So here we go,
Usage:
const MyTabs = TabNavigator({
...
}, {
tabBarComponent: TabBarBottom /* or TabBarTop */,
tabBarPosition: 'bottom' /* or 'top' */,
navigationOptions: ({ navigation }) => ({
tabBarOnPress: (scene, jumpToIndex) => {
console.log('onPress:', scene.route);
jumpToIndex(scene.index);
},
}),
});
I wasn't able to get this to work, and after checking the React Navigation documentation, found this, which seems to suggest that later versions (I'm using 1.0.0-beta.27) changed the method signature to a single object:
tabBarOnPress Callback to handle tap events; the argument is an object
containing:
the previousScene: { route, index } which is the scene we are leaving
the scene: { route, index } that was tapped
the jumpToIndex method
that can perform the navigation for you
https://reactnavigation.org/docs/en/tab-navigator.html#tabbaronpress
Given that, and the code from beausmith here, I put this together.
navigationOptions: ({ navigation }) => ({
tabBarOnPress: (args) => {
if (args.scene.focused) { // if tab currently focused tab
if (args.scene.route.index !== 0) { // if not on first screen of the StackNavigator in focused tab.
navigation.dispatch(NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: args.scene.route.routes[0].routeName }) // go to first screen of the StackNavigator
]
}))
}
} else {
args.jumpToIndex(args.scene.index) // go to another tab (the default behavior)
}
}
})
Note that you'll need to import NavigationActions from react-navigation for this to work.
Hope this helps somebody :)
Related
I want to create a header on top with title for each screen and button on the right to open the drawer in react navigation 3.x
In the code below the header does not show.
//Updated with Current code
import React, { Component } from 'react';
import { Button } from 'react-native';
import {
createStackNavigator,
createDrawerNavigator,
createAppContainer
} from 'react-navigation';
import MyHomeScreen from './components/HomeScreen';
import MyNotificationsScreen from './components/ProfileScreen';
const MyDrawerNavigator = createDrawerNavigator(
{
Home: {
screen: MyHomeScreen
},
Notifications: {
screen: MyNotificationsScreen
}
},
{
initialRouteName: 'Home',
navigationOptions: navigationOptionsHeader
}
);
const navigationOptionsHeader = ({ navigation }) => {
return {
headerTitle: 'MY Home',
headerRight: (
<Button
onPress={() => navigation.toggleDrawer()}
title="Info"
color="#222"
/>
)
};
};
const AppContainer = createAppContainer(MyDrawerNavigator);
class App extends Component {
render() {
return <AppContainer />;
}
}
export default App;
Use this inside your screen class
static navigationOptions = ({ navigation }) => {
return {
title: 'Home',
headerLeft: (
< Icon name="menu" size={30} style={{marginStart:10}} backgroundColor="#000000" onPress={() => navigation.openDrawer()} > < /Icon>
),
};
};
try this
const MyDrawerNavigator = createDrawerNavigator(
{
Home: {
screen: MyHomeScreen
},
Notifications: {
screen: MyNotificationsScreen
}
},
{
initialRouteName: 'Home'
navigationOptions: navigationOptionsHeader,
}
);
const navigationOptionsHeader=({navigation})=>{
return {
headerRight: (
<Button
onPress={() => navigation.toggleDrawer();
}
title="Info"
color="#222"
/>
)
};
}
you can also add other stuffs in header like this
const navigationOptionsHeader=({navigation})=>{
return {
headerRight: (
<Button
onPress={() => navigation.toggleDrawer();
}
title="Info"
color="#222"
/>
)
headerLeft : <headerLeft/>,
title: //Header Title
headerStyle: { backgroundColor: '#161616', height:48, },
headerTitleStyle:{ color:'#cd9bf0', fontWeight: '400', alignSe
};
}
The navigationoptions had been renamed as defaultNavigationOptions in v3.
Please refer the documentation from https://reactnavigation.org/docs/en/headers.html
For React Navigation 5
Use the prop options as a function:
<Stack.Screen
name="screen name"
component={ScreenComponent}
options={({ navigation }) => ({
headerRight: (props) => {
return <Button onPress={() => navigation.toggleDrawer() }} />
}
})}
/>
https://reactnavigation.org/docs/upgrading-from-4.x/#configuring-the-navigator
For react navigation 5.x
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
headerLeft: () => (
<View>
<Icon
onPress={() => navigation.toggleDrawer()}
name="menu"
/>
</View>
),
}}
/>
I am using react-navigation and as per the structure of my application, we have a tab navigator inside stack navigator, I am not been able to find any proper guide for implementing Deep-Linking.
https://v1.reactnavigation.org/docs/deep-linking.html. this doesn't give any reference for nested navigators.
You have to basically pass a path to every upper route untill you come to you nested route. This is indipendent of the type of navigator you use.
const HomeStack = createStackNavigator({
Article: {
screen: ArticleScreen,
path: 'article',
},
});
const SimpleApp = createAppContainer(createBottomTabNavigator({
Home: {
screen: HomeStack,
path: 'home',
},
}));
const prefix = Platform.OS == 'android' ? 'myapp://myapp/' : 'myapp://';
const MainApp = () => <SimpleApp uriPrefix={prefix} />;
In this case to route to an inner Navigator this is the route: myapp://home/article.
This example is using react-navigation#^3.0.0, but is easy to transfer to v1.
So, after the arrival of V3 of react navigation, things got extremely stable. Now i will present you a navigation structure with deep-linking in a Switch navigator -> drawerNavigator-> tabNavigator -> stack-> navigator. Please go step by step and understand the structure and keep referring to official documentation at everystep
With nested navigators people generally mean navigation structure which consists of drawer navigator, tab navigator and stackNavigator. In V3 we have SwitchNavigator too. So let's just get to the code,
//here we will have the basic React and react native imports which depends on what you want to render
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View, Animated, Easing, Image,
Button,
TouchableOpacity, TextInput, SafeAreaView, FlatList, Vibration, ActivityIndicator, PermissionsAndroid, Linking
} from "react-native";
import { createSwitchNavigator, createAppContainer, createDrawerNavigator, createBottomTabNavigator, createStackNavigator } from "react-navigation";
export default class App extends Component<Props> {
constructor() {
super()
this.state = {
isLoading: true
}
}
render() {
return <AppContainer uriPrefix={prefix} />;
}
}
class WelcomeScreen extends Component {
state = {
fadeAnim: new Animated.Value(0.2), // Initial value for opacity: 0
}
componentDidMount() {
Animated.timing( // Animate over time
this.state.fadeAnim, // The animated value to drive
{
toValue: 1,
easing: Easing.back(), // Animate to opacity: 1 (opaque)
duration: 1000,
useNativeDriver: true // Make it take a while
}
).start(); // Starts the animation
}
render() {
let { fadeAnim } = this.state;
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center", backgroundColor: '#000' }}>
<Animated.View // Special animatable View
style={{ opacity: fadeAnim }}
>
<TouchableOpacity
onPress={() => this.props.navigation.navigate("Dashboard")}
style={{
backgroundColor: "orange",
alignItems: "center",
justifyContent: "center",
height: 30,
width: 100,
borderRadius: 10,
borderColor: "#ccc",
borderWidth: 2,
marginBottom: 10
}}
>
<Text>Login</Text>
</TouchableOpacity>
</Animated.View>
<Animated.View // Special animatable View
style={{ opacity: fadeAnim }}
>
<TouchableOpacity
onPress={() => alert("buttonPressed")}
style={{
backgroundColor: "orange",
alignItems: "center",
justifyContent: "center",
height: 30,
width: 100,
borderRadius: 10,
borderColor: "#ccc",
borderWidth: 2
}}
>
<Text> Sign Up</Text>
</TouchableOpacity>
</Animated.View>
</View>
);
}
}
class Feed extends Component {
render() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Button
onPress={() => this.props.navigation.navigate("DetailsScreen")}
title="Go to details"
/>
</View>
);
}
}
class Profile extends Component {
render() {
return (
<SafeAreaView style={{ flex: 1, }}>
//Somecode
</SafeAreaView>
);
}
}
class Settings extends Component {
render() {
return (
<View style={{ flex: 1 }}>
//Some code
</View>
);
}
}
const feedStack = createStackNavigator({
Feed: {
screen: Feed,
path: 'feed',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Feed",
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
name="md-menu"
size={30}
onPress={() => navigation.openDrawer()}
/>
)
};
}
},
DetailsScreen: {
screen: Detail,
path: 'details',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Details",
};
}
}
});
const profileStack = createStackNavigator({
Profile: {
screen: Profile,
path: 'profile',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Profile",
headerMode: 'Float',
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
name="md-menu"
size={30}
onPress={() => navigation.openDrawer()}
/>
)
};
}
},
DetailsScreen: {
screen: Detail,
path: 'details',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Details"
};
}
}
});
const settingStack = createStackNavigator({
Settings: {
screen: Settings,
path: 'settings',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Settings",
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
name="md-menu"
size={30}
onPress={() => navigation.openDrawer()}
/>
)
};
}
},
DetailsScreen: {
screen: Detail,
path: 'details',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Details"
};
},
}
});
const DashboardTabNavigator = createBottomTabNavigator(
{
feedStack: {
screen: feedStack,
path: 'feedStack',
navigationOptions: ({ navigation }) => {
let tabBarVisible = true;
if (navigation.state.index > 0) {
tabBarVisible = false;
}
return {
tabBarLabel: "Feed",
tabBarVisible,
//iconName :`ios-list${focused ? '' : '-outline'}`,
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-list" color={tintColor} size={25} />
)
};
}
},
profileStack: {
screen: profileStack,
path: 'profileStack',
navigationOptions: ({ navigation, focused }) => {
let tabBarVisible = true;
if (navigation.state.index > 0) {
tabBarVisible = false
}
return {
tabBarVisible,
tabBarLabel: "Profile",
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-man" color={tintColor} size={25} />
)
};
// focused:true,
}
},
settingStack: {
screen: settingStack,
path: 'settingsStack',
navigationOptions: ({ navigation }) => {
let tabBarVisible = true;
if (navigation.state.index > 0) {
tabBarVisible = false;
}
return {
tabBarVisible,
tabBarLabel: "Settings",
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-options" color={tintColor} size={25} />
)
}
}
},
},
{
navigationOptions: ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
return {
// headerTitle: routeName,
header: null
};
},
tabBarOptions: {
//showLabel: true, // hide labels
activeTintColor: "orange", // active icon color
inactiveTintColor: "#586589" // inactive icon color
//activeBackgroundColor:'#32a1fe',
}
}
);
const DashboardStackNavigator = createStackNavigator(
{
DashboardTabNavigator: {
screen: DashboardTabNavigator,
path: 'dashboardtabs'
},
DetailsScreen: {
screen: Detail,
path: 'details',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Details"
};
}
}
},
{
defaultNavigationOptions: ({ navigation }) => {
return {
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
name="md-menu"
size={30}
onPress={() => navigation.openDrawer()}
/>
)
};
}
}
);
const AppDrawerNavigator = createDrawerNavigator({
Dashboard: {
screen: DashboardStackNavigator,
path: 'welcome'
},
DetailsScreen: {
screen: Detail,
path: 'friends',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Details",
};
}
}
});
//Switch navigator , will be first to load
const AppSwitchNavigator = createSwitchNavigator({
Welcome: {
screen: WelcomeScreen,
},
Dashboard: {
screen: AppDrawerNavigator,
path: 'welcome'
}
});
const prefix = 'myapp://';
const AppContainer = createAppContainer(AppSwitchNavigator);
For the process to setup React-navigation deep-linking please follow the official documentation
DetailsScreen was in my different folder and that will have class component of your choice
To launch the App the deep-link URL is myapp://welcome
To go to root page the deep-link URL is myapp://welcome/welcome
(this will reach at first page of first tab of tab navigator)
To go to any particular screen of tab navigator (suppose details
screen in profile tab) -
myapp://welcome/welcome/profileStack/details
const config = {
Tabs: {
screens: {
UserProfile: {
path: 'share//user_share/:userId',
parse: {
userId: (userId) => `${userId}`,
},
},
},
},
};
const linking = {
prefixes: ['recreative://'],
config,
};
if you have a screen in tab navigator you can do it like this via react-navigation v5
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
Having problem hiding the tabBar once we are inside StackNavigator which is inside TabRouter.
im using the navigatorOption, but it does not seem to be doing anything.
navigationOptions: {tabBarVisible: false}
can access expo.io from https://snack.expo.io/Sk4fQHAfZ
import React from 'react';
import {
Button,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import {
createNavigator,
createNavigationContainer,
TabRouter,
addNavigationHelpers,
StackNavigator,
} from 'react-navigation';
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView>
<Text>{banner}</Text>
<Button
onPress={() => {
navigation.goBack(null);
}}
title="Go back"
/>
</ScrollView>
);
const NestedMyNavScreen = ({ navigation, banner }) => (
<ScrollView>
<Text>{banner}</Text>
<Button
onPress={() => navigation.navigate('Profile', { name: 'Jane' })}
title="Go to a profile screen"
/>
<Button
onPress={() => navigation.navigate('Photos', { name: 'Jane' })}
title="Go to a photos screen"
/>
</ScrollView>
);
const MyNotificationsScreen = ({ navigation }) => (
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
);
const MySettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Settings Screen" navigation={navigation} />
);
const MyPhotosScreen = ({ navigation }) => {
let params = navigation.state.routes[navigation.state.index].params;
// let params = navigation.state.params;
return <MyNavScreen
banner={`${params.name}'s Photos`}
navigation={navigation}
/>
};
MyPhotosScreen.navigationOptions = {
title: 'Photos',
};
const MyProfileScreen = ({ navigation }) => {
let params = navigation.state.routes[navigation.state.index].params;
// let params = navigation.state.params;
return <MyNavScreen
banner={`${params.mode === 'edit' ? 'Now Editing ' : ''}${params.name}'s Profile`}
navigation={navigation}
/>
};
const CustomTabBar = ({ navigation }) => {
const { routes } = navigation.state;
return (
<View style={styles.tabContainer}>
{routes.map(route => (
<TouchableOpacity
onPress={() => navigation.navigate(route.routeName)}
style={styles.tab}
key={route.routeName}
>
<Text>{route.routeName}</Text>
</TouchableOpacity>
))}
</View>
);
};
const SimpleStack = StackNavigator({
NestedHome: {
screen: NestedMyNavScreen
},
Profile: {
path: 'people/:name',
screen: MyProfileScreen,
navigationOptions: {tabBarVisible: false}
},
Photos: {
path: 'photos/:name',
screen: MyPhotosScreen,
},
});
const CustomTabView = ({ router, navigation }) => {
const { routes, index } = navigation.state;
const ActiveScreen = router.getComponentForState(navigation.state);
return (
<View style={styles.container}>
<ActiveScreen
navigation={addNavigationHelpers({
...navigation,
state: routes[index],
})}
/>
<CustomTabBar navigation={navigation} />
</View>
);
};
const CustomTabRouter = TabRouter(
{
Home: {
screen: SimpleStack,
path: '',
},
Notifications: {
screen: MyNotificationsScreen,
path: 'notifications',
},
Settings: {
screen: MySettingsScreen,
path: 'settings',
},
},
{
// Change this to start on a different tab
initialRouteName: 'Home',
}
);
const CustomTabs = createNavigationContainer(
createNavigator(CustomTabRouter)(CustomTabView)
);
const styles = StyleSheet.create({
container: {
marginTop: Platform.OS === 'ios' ? 20 : 0,
flexDirection: 'column',
justifyContent: 'space-between',
flex: 1
},
tabContainer: {
flexDirection: 'row',
height: 48,
},
tab: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
margin: 4,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 4,
},
});
export default CustomTabs;
Seems like its not working when your using your custom tabRouter.
I got it to work removing it : https://snack.expo.io/H1NmvXE5b
(Also in your expo link you've wrongly used {tabBar : {visible:false}}
You can try and style your tab bar buttons either in each screen in the navigationOptions
OR
you could do it the way its done here:
(Just for example sake from the native-base docs:)
export default MainScreenNavigator = TabNavigator(
{
LucyChat: { screen: LucyChat },
JadeChat: { screen: JadeChat },
NineChat: { screen: NineChat }
},
{
tabBarPosition: "bottom",
tabBarComponent: props => {
return (
<Footer>
<FooterTab>
<Button
vertical
active={props.navigationState.index === 0}
onPress={() => props.navigation.navigate("LucyChat")}>
<Icon name="bowtie" />
<Text>Lucy</Text>
</Button>
<Button
vertical
active={props.navigationState.index === 1}
onPress={() => props.navigation.navigate("JadeChat")}>
<Icon name="briefcase" />
<Text>Nine</Text>
</Button>
<Button
vertical
active={props.navigationState.index === 2}
onPress={() => props.navigation.navigate("NineChat")}>
<Icon name="headset" />
<Text>Jade</Text>
</Button>
</FooterTab>
</Footer>
);
}
}
));
The problem is that you can only set navigation options for the navigator that renders a given screen. The screen that you want to hide the tab bar on is rendered by a stacknavigator, which does not have a tabBarVisible navigation option.
This link to the docs explains in more detail:
https://reactnavigation.org/docs/en/navigation-options-resolution.html#a-stack-contains-a-tab-navigator-and-you-want-to-set-the-title-on-the-stack-header
The solution is to set the navigation options in your stackNavigator, which is rendered by the tabNavigator. You can use a function to vary the navigation option per screen. Below is an example from the docs:
https://reactnavigation.org/docs/en/navigation-options-resolution.html#a-stack-contains-a-tab-navigator-and-you-want-to-set-the-title-on-the-stack-header
Here's another simple example:
const HomeStack = createStackNavigator(
{
Home: HomeScreen,
Settings: SettingsScreen
},
{
initialRouteName: "Home",
}
);
HomeStack.navigationOptions = ({ navigation }) => {
// get the name of the route
const { routeName } = navigation.state.routes[navigation.state.index];
if (routeName === 'Settings'){
tabBarVisible = false;
}
else{
tabBarVisible = true;
}
return {
tabBarVisible, // this now varies based on screen
tabBarLabel: "Search", // this is the same for all screens
};
};
export default createBottomTabNavigator(
{
HomeStack,
})
I want to implement tab navigator in react native.The link from which i get the code is
https://reactnavigation.org/docs/navigators/tab
The Problem is that when i run the code i get the error 500 type i also at the end attach the picture of the error.Plz resolve the issue if any one know about it the code is....
import React from 'react';
import {
AppRegistry,
Text,
} from 'react-native';
import { StackNavigator } from 'react-navigation';
class MyHomeScreen extends React.Component {
static navigationOptions = {
tabBarLabel: 'Home',
// Note: By default the icon is only shown on iOS. Search the showIcon option below.
tabBarIcon: ({ tintColor }) => (
<Image
source={require('./chats-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Notifications')}
title="Go to notifications"
/>
);
}
}
class MyNotificationsScreen extends React.Component {
static navigationOptions = {
tabBarLabel: 'Notifications',
tabBarIcon: ({ tintColor }) => (
<Image
source={require('./notif-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 26,
height: 26,
},
});
const MyApp = TabNavigator({
Home: {
screen: MyHomeScreen,
},
Notifications: {
screen: MyNotificationsScreen,
},
}, {
tabBarOptions: {
activeTintColor: '#e91e63',
},
});
AppRegistry.registerComponent('TabNavigator', () => MyApp);
when i run this code i get the error
Even i use the simple stack navigator on that time i also get the same error
the code of stack navigator i get from this link
https://reactnavigation.org/docs/intro/
The error tells you that a local image can not be found.
There are two options:
Create a chats-icon.png and a notif-icon.png and place them both in the directory where the file you copied the content from is at.
Replace source={require('./chats-icon.png')} and source={require('./chats-icon.png')} with source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}} to use an example remote image.
This should eliminate the 500 error and let you continue working.