I am using the new React-navigation from react-native. I have the navigation as follows:
StackNavigator:
TabNavigator // HomeNavigation
TabNavigator // NotificationNavigation
Full code:
const MainNavigation = StackNavigator({
Home: {
screen: HomeNavigation,
},
Notification: {
screen: NotificationNavigation,
}
});
const HomeNavigation = TabNavigator({
AllPost: {
screen: All,
},
ArticlePost: {
screen: Article,
},
BusinessPost: {
screen: Job,
},
});
HomeNavigation.navigationOptions = {
title: 'Home',
header: {
right: <SearchNotification/>
},
};
class SearchNotification extends React.Component {
goToNotification = () => {
this.props.navigate('Notification');
};
render() {
return (
<View style={styles.container}>
<TouchableOpacity>
<Icon name="md-search" style={styles.Icon}/>
</TouchableOpacity>
<TouchableOpacity style={styles.notificationWrapper} onPress={this.goToNotification}>
<Icon name="md-notifications" style={styles.Icon}/>
<Text style={styles.number}>3</Text>
</TouchableOpacity>
</View>
)
}
}
const NotificationNavigation = TabNavigator({
Comment: {
screen: NotificationComment,
},
Follow: {
screen: NotificationFollow,
}
});
HomeNavigation has a header, and the header has a right component of SearchNotification. SearchNotification has an icon which on press I would like to go to the NotificatoinNavigation.
However, if I make changes to the header of HomeNavigation to this way, the SearchNotification is not displayed in the header.
HomeNavigation.navigationOptions = {
title: 'Home',
header: {
tintColor: 'white',
style: {
backgroundColor: '#2ec76e',
},
right: ({navigate}) => <SearchNotification navigate={navigate}/>
},
};
How can I navigate to different screen from a button in a header?
So the problem was (I think), inside the navigationOptions instead of using navigations I had to use navigate, and pass it as a props to the child (i.e. the SearchNotification).
So the final code looks like this:
HomeNavigation.navigationOptions = {
title: 'Home',
header: ({navigate}) => ({
right: (
<SearchNotification navigate={navigate}/>
),
}),
};
And within the SearchNotification component:
export default class SearchNotification extends React.Component {
goToNotification = () => {
this.props.navigate('Notification');
};
render() {
return (
<View style={styles.container}>
<TouchableOpacity>
<Icon name="md-search" style={styles.Icon}/>
</TouchableOpacity>
<TouchableOpacity style={styles.notificationWrapper}
onPress={() => this.props.navigate('Notification')}>
<Icon name="md-notifications" style={styles.Icon}/>
<Text style={styles.number}>3</Text>
</TouchableOpacity>
</View>
)
}
}
Code that worked for me:
import Header from '../Containers/Header'
.........................................
navigationOptions: ({ navigation }) => ({
title: 'Find User',
headerRight: <Header navigation={navigation} />,
headerStyle: styles.header
})
And to move to other screen:
this.props.navigation.navigate('UserDetail', {});
Related
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.
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')}
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
I am building a react native app with a login and profile screen.The navigation is as below:
I wanted to change the header title when I navigate to each tabs.Also, i want my drawer to be able to open from any screen.So drawer icon should always be in the profile at left.
I cant make the header none/hide in profile screen as it will hide the drawer icon as well.Any idea how to solve it?
const TabStack = TabNavigator(
{
Home: {
screen: Home
},
Settings: {
screen: SettingsTab
}
}
);
const DrawerMain = DrawerNavigator(
{
TabStack: {
screen: TabStack
}
},
{
drawerOpenRoute: "DrawerOpen",
drawerCloseRoute: "DrawerClose"
);
const Profile = StackNavigator(
{
DrawerMain: {
screen: DrawerMain
}
},
{
headerMode: "screen",
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: "white"
},
headerLeft: (
<TouchableOpacity
onPress={() => {
if (navigation.state.index === 0) {
navigation.navigate("DrawerOpen");
} else {
navigation.navigate("DrawerClose");
}
}}
>
<Icon name={"ios-menu"} size={20} style={{ color: "red" }} />
</TouchableOpacity>
)
})
}
);
export default (App = StackNavigator({
Login: {
screen: Login
},
Profile: {
screen: Profile,
}
}));
This is how the profile should look like.
First, change your navigation hierarchy to like this.
Drawer
ㄴ Stack
__ ㄴ Tab
Then, you need to pass DrawerNavigator's navigation to StackNavigator to control a drawer from a button in StackNavigator.
And use it through screenProps.
...
const Profile = StackNavigator(
{
TabStack: {
screen: TabStack
}
},
navigationOptions: ({ screenProps }) => ({
...
headerLeft: (
<TouchableOpacity
onPress={() => {
screenProps.myDrawerNavigation.navigate("DrawerOpen");
}}
>
<Icon name={"ios-menu"} size={20} style={{ color: "red" }} />
</TouchableOpacity>
)
...
const DrawerMain = DrawerNavigator(
{
Profile: {
screen: ({navigation}) => <Profile screenProps={{myDrawerNavigation:navigation}}/>
}
},
...
Style styles.draweritemstxt_active and styles.draweritemstxt_inactive not set / rerender when I try to choose other drawer item.
Navigator.js
const MainDrawer = DrawerNavigator({
Event: { screen: EventScreen },
Wallet: { screen: WalletScreen},
Profile: { screen: ProfileScreen},
Contact: { screen: MemberContactScreen},
Reward: { screen: MemberRewardScreen},
},{
contentComponent: props => <DrawerScreen {...props} />
});
DrawserScreen.js
const DrawserScreen = props => {
let totalitem = props.items;
return(
<ScrollView style={{backgroundColor:'#000'}}>
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
{
totalitem.map((ritem,i)=>{
let txtstyle = null;
if(props.activeItemKey == ritem.key){
txtstyle = styles.draweritemstxt_active;
}else{
txtstyle = styles.draweritemstxt_inactive;
}
return(
<TouchableHighlight key={i} activeOpacity={0.9} onPress={()=> props.navigation.navigate(ritem.key)} style={styles.draweritems}>
<View>
<Text style={txtstyle}>{_convertRouteToTitle(ritem.routeName)}</Text>
</View>
</TouchableHighlight>
);
})
}
</SafeAreaView>
</ScrollView>
);
}
export default DrawserScreen;