React Navigation how to pass props to TabNavigator Stateless Functional Components - reactjs

I am learning to use React Navigation and loving it, but can't figure out how to send props from my top level App Component down to my screen components. I could be (most probably) going about it completely the wrong way. Here is my code.
Main App Component
class App extends Component {
constructor(props) {
super(props);
this.state = {
signedIn: false,
checkedSignIn: false
};
}
componentWillMount() {
isSignedIn()
.then(res => this.setState({ signedIn: res, checkedSignIn: true }))
.catch(err => alert(err));
}
render() {
const { checkedSignIn, signedIn } = this.state;
if (!checkedSignIn) {
return null;
}
if (signedIn) {
console.log("yeah boi");
console.log(SignedOut);
return (
<Provider store={store}>
<SignedIn screenProps={(name = "TestName")} />
</Provider>
);
} else {
console.log("nah bro");
return (
<Provider store={store}>
<SignedOut />
</Provider>
);
}
}
}
Screen
export default ({ navigation }) =>
<View style={{ paddingVertical: 20 }}>
<Card title="John Doe">
<View
style={{
backgroundColor: "#bcbec1",
alignItems: "center",
justifyContent: "center",
width: 80,
height: 80,
borderRadius: 40,
alignSelf: "center",
marginBottom: 20
}}
>
<Text style={{ color: "white", fontSize: 28 }}>JD</Text>
</View>
<Button
title="SIGN OUT"
onPress={() =>
onSignOut().then(() => navigation.navigate("SignedOut"))} // NEW LOGIC
/>
</Card>
</View>;
Nav
export const SignedIn = TabNavigator({
Tasks: {
screen: Tasks,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="list" size={30} />
}
},
Home: {
screen: Home,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="home" size={30} />
}
},
Message: {
screen: Message,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="envelope-letter" size={30} />
}
},
Profile: {
screen: Profile,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="user" size={30} />
}
}
});
Can anyone tell me how I would pass props, such as my attempted {(name = "TestName")}, to the SignedIn SFC?
I am fairly new to react so please be gentle :)
Thanks
Sam

Got it sorted while still keeping the items stateless, using React Navigations screenProps parameter. Just had to fix my syntax in the Nav component and explicitly call screenProps in my screen. Here it is for reference:
Main App
class App extends Component {
constructor(props) {
super(props);
this.state = {
signedIn: false,
checkedSignIn: false
};
}
componentWillMount() {
isSignedIn()
.then(res => this.setState({ signedIn: res, checkedSignIn: true }))
.catch(err => alert(err));
}
render() {
const { checkedSignIn, signedIn } = this.state;
if (!checkedSignIn) {
return null;
}
if (signedIn) {
console.log("yeah boi");
console.log(SignedOut);
return (
<Provider store={store}>
<SignedIn screenProps={{ name: "TestName" }} />
</Provider>
);
} else {
console.log("nah bro");
return (
<Provider store={store}>
<SignedOut />
</Provider>
);
}
}
}
Screen
export default ({ navigation, screenProps }) =>
<View style={{ paddingVertical: 20 }}>
<Card title={screenProps.name}>
<View
style={{
backgroundColor: "#bcbec1",
alignItems: "center",
justifyContent: "center",
width: 80,
height: 80,
borderRadius: 40,
alignSelf: "center",
marginBottom: 20
}}
>
<Text style={{ color: "white", fontSize: 28 }}>JD</Text>
</View>
<Button
title="SIGN OUT"
onPress={() =>
onSignOut().then(() => navigation.navigate("SignedOut"))} // NEW LOGIC
/>
</Card>
</View>;
Nav
export const SignedIn = TabNavigator({
Tasks: {
screen: Tasks,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="list" size={30} />
}
},
Home: {
screen: Home,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="home" size={30} />
}
},
Message: {
screen: Message,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="envelope-letter" size={30} />
}
},
Profile: {
screen: Profile,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name="user" size={30} />
}
}
});

Use store state to get data, set state of store in top level component,
use that state in your screen component

I think <SignedIn screenProps={(name = "TestName")} /> will rise a syntax error. It should be just <SignedIn name='TestName' />. The bigger problem is how you use the TabNavigator component. What if you try the following:
export const SignedIn = ({ name }) => TabNavigator({
Tasks: {
screen: Tasks,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name={ name } size={30} />
}
},
Home: {
screen: Home,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name={ name } size={30} />
}
},
Message: {
screen: Message,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name={ name } size={30} />
}
},
Profile: {
screen: Profile,
navigationOptions: {
tabBarIcon: ({ tintColor }) =>
<SimpleLineIcons name={ name } size={30} />
}
}
});

Related

Unable to remove existing params in react navigation

I'm using react-navigation v4 for my expo App. For my App I'm using createDrawerNavigator and createSwitchNavigator with createAppContainer and createBrowserApp for web.
My issue is when I'm navigating to a route where I don't want params, there also it's passing me parameters. like,
http://localhost:19006/App/SkyView (first I visited route without
params)
http://localhost:19006/App/CasesList (I visited another route, from
there I'm passing params to SkyView route)
it redirect me to http://localhost:19006/App/SkyView?caseId=HYDE200627-00064&tripIndex=0
after that If I want to visit http://localhost:19006/App/SkyView it navigating to http://localhost:19006/App/SkyView?caseId=HYDE200627-00064&tripIndex=0
My DrawerNavigator code
const DrawerNavigation = createDrawerNavigator({
CasesList: {
screen: MainAuth(CasesList),
navigationOptions: {
drawerIcon: ({ tintColor }) => (<FontAwesome5 name='map-marked-alt' size={18} style={{color:tintColor}}/>)
}
},
SkyView: {
screen: MainAuth(SkyView),
navigationOptions: {
drawerIcon: ({ tintColor }) => (<FontAwesome5 name='map-marked-alt' size={18} style={{color:tintColor}}/>)
}
},
},{contentComponent: props => <CustomDrawerContentComponent {...props}/>,contentOptions: {
activeTintColor: baseColor,
itemsContainerStyle: {
marginVertical: 0,
},
iconContainerStyle: {
opacity: 1
}
}})
const CustomDrawerContentComponent = props => {
const signOutAsync = async () => {
try {
store.dispatch(logoutHandler())
props.navigation.navigate('Auth');
}
catch(exception) {
console.log(exception)
}
};
return (
<ScrollView contentContainerStyle={styles.container}>
<SafeAreaView
forceInset={{ top: 'always', horizontal: 'never' }}
>
<View style={styles.header}>
<View style={styles.avatar}>
<FontAwesome5 name="user-alt" size={24} style={{color:white}}/>
</View>
<View style={styles.userInfo}>
<Text style={{}}>Abdulla Zulqarnain</Text>
</View>
</View>
<DrawerItems {...props} />
</SafeAreaView>
<TouchableOpacity onPress={()=>signOutAsync()}>
<View style={styles.item}>
<View style={styles.iconContainer}>
<FontAwesome5 name='sign-out-alt' size={18} style={{color:red_dark}}/>
</View>
<Text style={styles.label}>Logout</Text>
</View>
</TouchableOpacity>
</ScrollView>
);
}
other Routing code
const routes = createSwitchNavigator(
{
AuthLoading: {
screen: AuthLoadingScreen,
navigationOptions: {
header: null,
}
},
App: {
screen: DrawerNavigation,//MainAuth(CasesList),
navigationOptions: {
header: null,
}
},
Auth:{
screen: Login,
navigationOptions: {
tabBarVisible: false,
header: null,
},
},
HospitalList: {
screen: HospitalList,
navigationOptions: {
header: null,
}
},
},
{
initialRouteName: 'AuthLoading',
defaultNavigationOptions: {
}
}
);
const container = isWeb ? createBrowserApp(routes): createAppContainer(routes);
I'm stuck since 2 days can anyone help me to sortout this issue.

Flat List navigation react native

I been having an issue with navigating from API flat list to separate screen. I got a news api integrated and I want to from each article render to navigate to newsdetail screen. I'm not getting an error message only touchable opacity is not working. I'm not sure where I made a mistake in the flatlist or in the APP.js
FlatList:
import React, { Component } from 'react';
import { FlatList, TouchableOpacity } from 'react-native';
import { getUSANews } from './fetchNews';
import Article from './Article';
import NewsDetail from '../screens/NewsDetail';
class News extends Component {
state = {
articles: [],
refreshing: true
};
componentDidMount = () => {
this.fetchNews();
};
fetchNews = () => {
getUSANews()
.then(articles => {
this.setState({ articles, refreshing: false });
})
.catch(() => this.setState({ refreshing: false }));
};
handleRefresh = () => {
this.setState({ refreshing: true }, () => this.fetchNews());
};
render(navigation) {
return (
<FlatList
data={this.state.articles}
keyExtractor={item => item.url}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh}
renderItem ={({item}) => {
return (
<TouchableOpacity onPress={() => this.props.navigation.navigate('NewsDetail')}
>
<Article article={item} />
</TouchableOpacity>
);
}}
/>
);
}
}
export default News;
App.js:
const Drawer = createDrawerNavigator(
{
Home: {
screen: homeScreen,
Options: {
title: 'Home',
activeTintColor: 'red'
},
},
Signin:{
screen: SigninScreen,
Options: {
title: "Sign In",
},
},
Signup: {
screen: SignupScreen,
navigationOptions: {
title: 'Sign Up'
}
}
},
{
initialRouteName: 'Home',
unmountInactiveRoutes: true,
headerMode: 'none',
contentOptions: {
activeTintColor: 'red'
},
},
);
const AppNavigator = createStackNavigator({
Drawer: {
screen: Drawer,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Home",
headerTitleStyle: {
color: "white"
},
headerStyle: {
backgroundColor: "#5BBC9D"
},
headerLeft: (
<Icon
onPress={() => navigation.openDrawer()}
name="md-menu"
color="white"
size={30}
style={{
paddingLeft: 10
}}
/>
),
headerRight: (
<Icon
onPress={() => navigation.se()}
name="ios-search"
color="white"
size={30}
style={{
paddingRight: 10
}}
/>
)
}
}},
Detail: {
screen:NewsDetail
}
})
const AppContainer = createAppContainer(AppNavigator);
export default class App extends React.Component {
render (){
return(
<AppContainer />
);
}
}
You don't have any screen name NewsDetail change this:
onPress={() => this.props.navigation.navigate('NewsDetail')}
to
onPress={() => this.props.navigation.navigate('Detail')}
Hope this helps!
You set the RouteName to your newsDetail screen as Detail. Hence to navigate to that screen you need to use the RouteName you set and not the screen name. Kindly change from;
onPress={() => this.props.navigation.navigate('NewsDetail')}
to
onPress={() => this.props.navigation.navigate('Detail')}

Can't show custom header in tabNavigator

I can't show my custom header with static navigation options. It's only TabNavigator on my Title. What should I do?
This is my HomeScreen Component;
export default class Home extends Component {
static navigationOptions = ({navigation}) => ({
title: 'MENEMENOYS',
headerLeft : (
<TouchableOpacity
onPress={() => {
AuthStore.LogOut().then(() => {
navigation.navigate('LoginPage');
});
}}>
<Icon
name="md-log-out"
size={30}
color={'white'}
style={{marginLeft:10}}
/>
</TouchableOpacity>
)
})
And this is my router : stack navigator with tab navigator.
const TabNavigator = createBottomTabNavigator(
{
Home: {
screen: Home,
navigationOptions: {
tabBarIcon: ({ tintColor }) => (
<Icon
name="md-home"
size={30}
color={tintColor}
style={styles.homeIcon}
/>
),
},
},
AddNewCar: {
screen: AddNewCar,
navigationOptions: {
tabBarIcon: ({ tintColor }) => (
<Icon
name="md-add-circle"
size={40}
color={tintColor}
style={styles.addIcon}
/>
),
},
},
OtoparkList: {
screen: OtoparkList,
navigationOptions: {
tabBarIcon: ({ tintColor }) => (
<IconAwesome name="car" size={30} color={tintColor} />
),
},
},
},
{
tabBarOptions: {
showLabel: false,
activeTintColor: '#41AB5F',
inactiveTintColor: 'white',
style: {
backgroundColor: '#1F202D',
borderTopColor: 'transparent',
},
},
},
);
const AppNavigator = createStackNavigator(
{
TabNavigator: {
screen: TabNavigator,
navigationOptions: {
}
},
LoginPage: {
screen: LoginPage,
navigationOptions: {
headerShown: false,
},
},
ParkingDetail: {
screen: ParkingDetail,
navigationOptions: {
headerShown: false,
},
},
Print: {
screen: Print,
navigationOptions: {
headerShown: false,
}
}
},
{
initialRouteName: 'LoginPage',
},
);
But my header is not shown. Only Header title:TabNavigator and default back button.
Where am i doing wrong ? Please help me. Thanks.
Hey in React navigation latest version 5.x syntax is changed try following
Take a look at doc here Header buttons
static navigationOptions = ({ navigation }) => {
return {
headerTitle: () =>(
<View>
<Text>MENEMENOYS</Text>
</View>
),
headerLeft: () => (
<TouchableOpacity
onPress={() => {
AuthStore.LogOut().then(() => {
navigation.navigate('LoginPage');
});
}}>
<Icon
name="md-log-out"
size={30}
color={'white'}
style={{marginLeft:10}}
/>
</TouchableOpacity>
),
};
};

State params getting undefined in react-navigation

When I am trying to do setParams with navigation in componentDidMount() and try to access in static navigationOptions = {} but it's not setting the params in navigation state object and getting undefined.
I am currently using below version
react-navigation 3.9.1
react-native Using with EXPO SDK 32.0
ManTabNavigator.js
const HomeStack = createStackNavigator({
Home: { screen: HomeScreen },
Service: { screen: ServiceListScreen },
}, {
initialRouteName: 'Home',
});
HomeStack.navigationOptions = {
tabBarLabel: 'Home',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
type={'MaterialIcons'}
name={'home'}
/>
),
export default createBottomTabNavigator({
HomeStack,
LinksStack,
SettingsStack,
}, {
initialRouteName: 'HomeStack',
activeColor: '#19CF86',
inactiveColor: 'rgba(0, 0, 0, 0.3)',
barStyle: { backgroundColor: '#ffffff' },
});
};
ServiceListScreen.js
class ServiceListScreen extends Component {
static navigationOptions = {
header: ({ navigation }) => {
return (
<Header>
<ServiceTab
services={{}}
/>
</Header>
)
}
};
_setNavigationParams() {
let title = 'Form';
this.props.navigation.setParams({
title,
});
}
componentDidMount() {
this._setNavigationParams();
}
render() {
const { selectedService } = this.props;
return (
<KeyboardAwareScrollView>
<SafeAreaView
// style={styles.container}
forceInset={{ top: 'always' }}
>
<View style={{ flex: 1 }}>
<SubServiceList
selectedService={selectedService}
/>
</View>
</SafeAreaView>
</KeyboardAwareScrollView>
);
}
}
ServiceListScreen.propTypes = {
services: PropTypes.object,
selectedService: PropTypes.object,
// actions
};
const mapStateToProps = (state, ownProps) => {
return {
services: getAllServices(state),
selectedService: getSelectedServices(state),
};
}
export default compose(
withNavigation,
connect(mapStateToProps),
)(ServiceListScreen);
navigationOptions is not the same as the navigation params. If you don't need to dynamically set the title, you could do this instead:
static navigationOptions = {
title: 'Form',
header: () => (
<Header>
<ServiceTab services={{}} />
</Header>
)
}
If you do need access to the navigation params, then do so like this:
static navigationOptions = ({ navigation }) => ({
title: navigation.getParam('title', ''), // fallback to empty string
header: () => (
<Header>
<ServiceTab services={{}} />
</Header>
)
})
this is how i use navigationOptions
static navigationOptions = ({ navigation }) => {
return {
title: navigation.state.params.type ? navigation.state.params.type : 'Members',
headerStyle: {
backgroundColor: Colors.primaryColor,
},
headerTintColor: Colors.white,
headerTitleStyle: {
fontWeight: 'bold',
},
headerMode: 'float',
headerLeft: <Icon
onPress={() => navigation.goBack()}
name="arrow-back"
type='MaterialIcons'
style={{ color: 'white', marginLeft: 10 }}
/>,
}
}
make sure you are getting params correctly from navigation
format: title: navigation.state.params.title

react native createbottomtabnavigator hide tab bar label

I need to know how to hide the bottom label.
I've tried the following:
tabBarShowLabels: 'hidden', tabbarlabelvisible: false.
I also removed the tabbarlabel: 'Home' and it still shows
Any help would be appreciated or if someone could point me to the right direction.
import {createBottomTabNavigator} from 'react-navigation'
import Icon from 'react-native-vector-icons/Ionicons'
const Tabs = createBottomTabNavigator ({
Home:{
screen: Home,
navigationOptions:{
tabBarIcon: ({ focused, tintcolor }) => (
<Icon name="ios-home" size={24} />
)
}
},
Inbox:{screen: Inbox,
navigationOptions:{
tabBarIcon: ({ tintcolor }) => (
<Icon name="ios-mail" size={24} />
)
}
},
Search:{screen: Search,
navigationOptions:{
tabBarIcon: ({ tintcolor }) => (
<Icon name="ios-search" size={24} />
)
}
},
Favorites:{screen: Favorites,
navigationOptions:{
tabBarIcon: ({ tintcolor }) => (
<Icon name="ios-heart" size={24} />
)
}
},
Settings:{screen: Settings,
navigationOptions:{
tabBarIcon: ({ tintcolor }) => (
<Icon name="ios-settings" size={24} />
)
}
}
}
});
export default class App extends Component {
render() {
return <Tabs />
}
}
You have to define showLabel: false as the docs says, just as
const Tabs = createBottomTabNavigator ({
Home:{
screen: Home,
navigationOptions:{
tabBarIcon: ({ focused, tintcolor }) => (
<Icon name="ios-home" size={24} />
)
}
},
...
,
Settings:{screen: Settings,
navigationOptions:{
tabBarIcon: ({ tintcolor }) => (
<Icon name="ios-settings" size={24} />
)
}
}
}
}, {
tabBarOptions: { showLabel: false }
});
On the new versions of React Navigation, you just need to pass showLabel prop as false
<Tab.Navigator tabBarOptions={{ showLabel: false }}>
The above answer is perfect, But it messed the brackets a bit. So for a new bee like me, Here is the proper code.
const ProfileStack = createStackNavigator({
Profile: SettingsScreen
});
ProfileStack.navigationOptions = {
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
title={'Profile'}
name={focused ? 'tabIcon' : 'tabIconFocused'}
/>
),
tabBarOptions: { showLabel: false }
};
compatible with v6
<Tab.Navigator
screenOptions={() => ({
tabBarShowLabel: false,
....
for react-navigation v4, set the labeled property to false to display only the icons.
const Tabs = createBottomTabNavigator ({
Home:{
screen: Home,
navigationOptions:{
tabBarIcon: ({ focused, tintcolor }) => (
<Icon name="ios-home" size={24} />
)
}
},
...
,
Settings:{screen: Settings,
navigationOptions:{
tabBarIcon: ({ tintcolor }) => (
<Icon name="ios-settings" size={24} />
)
}
}
}
}, {labeled:false});
Use tabBarShowLabel property
tabBarShowLabel: false,
Code
<NavigationContainer>
<BottomTab.Navigator
screenOptions={{
activeTintColor: '#000',
inactiveTintColor: '#fff',
tabBarActiveTintColor: 'black',
tabBarInactiveTintColor: 'gray',
//this one
tabBarShowLabel: false,
}
<BottomTab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarIcon: ({ focused }) => (
<Icon
name={focused ? 'home' : 'home-outline'}
size={24}
color={focused && 'black'}
/>
),
}}
/>
----
----
</BottomTab.Navigator>
</NavigationContainer>

Resources