Flat List navigation react native - reactjs

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

Related

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

rerender component when tab is choosed react-native

I'm using TabNavigator from react-navigation to navigate through 3 component. My TabNavigator component look like this:
import routeOnMap from '../screens/routsOnMap.js';
import meditatinWalk from '../screens/meditationWalk.js';
import newWordToWalkOn from '../screens/newWordToWalkOn.js';
import * as firebase from 'firebase';
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Button
} from 'react-native';
import {
StackNavigator,
NavigationActions,
TabNavigator,
TabBarBottom,
} from 'react-navigation';
import Ionicons from 'react-native-vector-icons/Ionicons';
export default TabNavigator(
{
MeditatinWalk: { screen: meditatinWalk },
NewWordToWalkOn: { screen: newWordToWalkOn },
RouteOnMap: { screen: routeOnMap },
},
{
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'MeditatinWalk') {
iconName = `ios-walk${focused ? '' : '-outline'}`;
} else if (routeName === 'NewWordToWalkOn') {
iconName = `ios-add-circle${focused ? '' : '-outline'}`;
} else if (routeName === 'RouteOnMap') {
iconName = `ios-map${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: '#626A41',
inactiveTintColor: 'gray',
},
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false,
}
);
I want to rerender whats inside my NewWordToWalkOn component when it's when it is pressed/tabbed. The code I would like to rerender is whats inside the componentDidMount() methode in the NewWordToWalkOn component.
//imports
export default class NewWordToWalkOn extends Component {
constructor() {
super()
this.state = {
words: [],
};
}
static navigationOptions = ({ navigation }) => ({
title:
<Text style={{ fontWeight: 'bold', color: '#626A41'}}> Vælg nye ord at vandre på </Text>,
headerLeft: null,
headerRight:
<TouchableOpacity
style={{ flex: 1, alignItems: 'center', justifyContent: 'center', marginRight: 10 }}
onPress={ () => MeditatinWalk._logout() }>
<Text
style={{ fontWeight: 'bold', color: '#626A41'}}>
Log ud
</Text>
</TouchableOpacity>
});
componentDidMount() {
//code that needs rerendered
}
render() {
)
return (
<ScrollView style={styles.wrapper}>
//all the elements
</ScrollView>
);
}
}
Any suggestions how to rerender?
If you want to update your view when the tab is pressed, try subscribe navigation lifecycle event with this.props.navigation.addListener.
Example:
class NewWordToWalkOn extends Component {
constructor (props) {
super(props)
this.navigationWillFocusListener = props.navigation.addListener('willFocus', () => {
// do something like this.setState() to update your view
})
}
componentWillUnmount () {
this.navigationWillFocusListener.remove()
}
}

ReactNative:How to change the header for tab navigator inside a drawer navigator

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}}/>
}
},
...

Navigate to different screen from a button in a header

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', {});

Resources