Call onPress method from imported UI navbar component - react-native

I am building an app that displays jobs and the commute time for each of them. I have a JobsComponent, where I display the jobs. In this component, I have added an icon on the navbar. When the icon is tapped, a MapComponent should be opened. In this map, I want to display a pin for each job.
The problem that I'm facing is that I've defined the icon in my AppNavigator.js and I want to have the onPress() functionality in JobsComponent.js, but I don't know how to do this. What I've tried:
Adding an ({ onPress }) param to navHeaderRight:
export const navHeaderRight = ({ onPress }) =>
(/UI component goes here/
)
but with no results.
One other idea I had was to define the onPress() behaviour in AppNavigator.js, but this means importing a lot of stuff (array of jobs, details for each job) to AppNavigator.js, which is not a good design decision from my point of view.
I tried just doing a console.log in navHeaderRight.onPress from JobsComponent to see if it works at all. It doesn't.
This is my AppNavigator.js:
import {TouchableHighlight, Image, View} from 'react-native';
import MapComponent from './MapComponent';
export const navHeaderRight = ({ onPress }) =>
(
<View style={{marginRight: 5}}>
<TouchableHighlight underlayColor="transparent">
<Image
source={require('../assets/map.png')}
style={{height: 40, width: 40}}/>
</TouchableHighlight>
</View>
)
const Navigator = createStackNavigator({
Jobs: {
screen: Jobs,
navigationOptions: {
headerRight: navHeaderRight
}
},
MapComponent: {
screen: MapComponent,
navigationOptions: {
header: null
}
}
//other screens defined in the navigator go here
});
const AppNavigator = createAppContainer(Navigator);
export default AppNavigator;
And this is my JobsComponent.js. Here, I try to define the onPress() behaviour in componentDidMount().
import {navHeaderRight} from './AppNavigator';
class Jobs extends Component {
componentDidMount() {
navHeaderRight.onPress = () => {
this.props.navigation.navigate('MapComponent', {/*other params go here*/})
}
}
}
Expected result: when navHeaderRight.onPress is called, the MapComponent should be opened.
**
Actual result: Nothing happens.
**
Any help will be greatly appreciated. :)

You can use React Navigation route parameters to achieve this.
In AppNavigator.js:
import { TouchableHighlight, Image, View } from 'react-native';
import MapComponent from './MapComponent';
const navHeaderRight = (navigation) => {
const handlePress = navigation.getParam('handlePress', null);
return (
<View style={{marginRight: 5}}>
<TouchableHighlight
underlayColor="transparent"
onPress={handlePress}
>
<Image
source={require('../assets/map.png')}
style={{height: 40, width: 40}}
/>
</TouchableHighlight>
</View>
);
}
const Navigator = createStackNavigator({
Jobs: {
screen: Jobs,
navigationOptions: ({ navigation }) => ({
headerRight: navHeaderRight(navigation),
}),
},
MapComponent: {
screen: MapComponent,
navigationOptions: {
header: null,
}
}
});
const AppNavigator = createAppContainer(Navigator);
export default AppNavigator;
In JobsComponent.js:
class Jobs extends Component {
componentDidMount() {
const handlePress = () => console.log('whatever function you want');
this.props.navigation.setParams({ handlePress });
}
// [...]
}

Related

Dynamically change header title in react native navigation

For a school assignment we're creating an app in react native with react navigation and redux. Because all of us are new to react we have an issue we are unable to resolve.
We want to change the title of the header when a certain button is clicked. The first time we click a button it changes the header title just fine. The problem arrises when we press a different button, the header doesn't change. Note that no matter what option we choose, we always go to the same screen.
import React from 'react';
import { createStackNavigator, createAppContainer, createDrawerNavigator } from 'react-navigation';
import {connect} from 'react-redux';
import { store } from '#redux/MyStore';
import { Ionicons } from '#expo/vector-icons';
import ScannerScreen from '#screens/ContactScreen';
import EventsScreen from '#screens/ListScreen';
const ContactStack = createStackNavigator({
Contact: {
screen: ContactScreen,
navigationOptions: ({navigation}) => ({
headerStyle: {backgroundColor: '#fa8231'},
headerTitleStyle: {fontSize: 18},
title: store.getState().setupState.title,
headerLeft: <Ionicons
name="md-menu" style={{marginLeft:10}}
size={28}
onPress={() => navigation.toggleDrawer()} /> //menu button
})
}
});
// Code to create stack for the ListStack
const DrawerStack = createDrawerNavigator({
Contact: ContactStack,
List: ListStack
});
const PrimaryNavigation = createStackNavigator({
ListStack: {
screen: ListStack,
navigationOptions: {
header: null,
},
},
DrawerStack: {
screen: DrawerStack,
navigationOptions: {
header: null,
},
},
},
{
initialRouteName: 'ListStack',
});
const AppContainer = createAppContainer(PrimaryNavigation);
class AppNavigation extends React.Component {
render() {
return <AppContainer/>
}
}
export default (AppNavigation)
We did get it working when we put the title bar in the DrawerNavigator, but since we want the Drawer in from of the header that is not an option. My speculation is that the stack is created once with a certain title and never gets updated when switching screens using the DrawerNavigator but we have no clue how to fix that.
Thanks in advance!
From what I understand you need to change the title when a screen is loaded in stack.So you could use some like:
class ScreenInContactStack extends React.Component{
//Constryctor
static navigationOptions = ({navigation}) => ({
title: (navigation.state.params || {}).title || 'Chat! ',
});
//Remaining Logic
}
and while calling
this.props.navigation.navigate('ScreenInContactStack', {title: yourTitle + ' ',});
Don't know why but the Appbar condense the title to like yourTi.. to avoid this add a space to the title.
Try this:
map title as a prop to force ContactStack to re-render whenever it changes
class ContactStack extends React.Component {
render() {
const { title } = this.props.setupState;
const Stack = createStackNavigator({
Contact: {
screen: ContactScreen,
navigationOptions: ({navigation}) => ({
headerStyle: {backgroundColor: '#fa8231'},
headerTitleStyle: {fontSize: 18},
title,
headerLeft: <Ionicons
name="md-menu" style={{marginLeft:10}}
size={28}
onPress={() => navigation.toggleDrawer()} /> //menu button
})
}
});
return <Stack />;
}
}
const mapStateToProps = ({ setupState }) => ({setupState});
export default connect(mapStateToProps)(ContactStack);

withNavigation can only be used on a view hierarchy of a navigator

I'm getting the error:
Invariant Violation: withNavigation can only be used on a view
hierarchy of a navigator. The wrapped component is unable to get
access to navigation from props or context
I don't know why, because I'm using withNavigation in other components in my app and it works. I don't see a difference in the components that it works on to the one that causes the error.
Code:
the component:
const mapStateToProps = (state: State): Object => ({
alertModal: state.formControls.alertModal
})
const mapDispatchToProps = (dispatch: Dispatch<*>): Object => {
return bindActionCreators(
{
updateAlertModalHeight: updateAlertModalHeight,
updateAlertModalIsOpen: updateAlertModalIsOpen,
updateHasYesNo: updateAlertModalHasYesNo
},
dispatch
)
}
class AlertModalView extends Component<AlertModalProps, State> {
render(): Node {
return (
<View style={alertModalStyle.container}>
<PresentationalModal
style={presentationalModalStyle}
isOpen={this.props.alertModal.isOpen}
title={this.props.alertModal.title}
navigation={this.props.navigation}
updateHasYesNo={this.props.updateHasYesNo}
message={this.props.alertModal.message}
updateAlertModalHeight={this.props.updateAlertModalHeight}
viewHeight={this.props.alertModal.viewHeight}
hasYesNo={this.props.alertModal.hasYesNo}
yesClicked={this.props.alertModal.yesClicked}
updateAlertModalIsOpen={this.props.updateAlertModalIsOpen}
/>
</View>
)
}
}
// $FlowFixMe
const AlertModalViewComponent = connect(
mapStateToProps,
mapDispatchToProps
)(AlertModalView)
export default withNavigation(AlertModalViewComponent)
the stackNavigator:
import React from 'react'
import { View, SafeAreaView } from 'react-native'
import Icon from 'react-native-vector-icons/EvilIcons'
import Add from '../product/add/view'
import Login from '../user/login/view'
import Search from '../product/search/query/view'
import { Image } from 'react-native'
import { StackNavigator, DrawerNavigator, DrawerItems } from 'react-navigation'
const AddMenuIcon = ({ navigate }) => (
<View>
<Icon
name="plus"
size={30}
color="#FFF"
onPress={() => navigate('DrawerOpen')}
/>
</View>
)
const SearchMenuIcon = ({ navigate }) => (
<Icon
name="search"
size={30}
color="#FFF"
onPress={() => navigate('DrawerOpen')}
/>
)
const Stack = {
Login: {
screen: Login
},
Search: {
screen: Search
},
Add: {
screen: Add
}
}
const DrawerRoutes = {
Login: {
name: 'Login',
screen: Login
},
'Search Vegan': {
name: 'Search',
screen: StackNavigator(Stack.Search, {
headerMode: 'none'
}),
navigationOptions: ({ navigation }) => ({
drawerIcon: SearchMenuIcon(navigation)
})
},
'Add vegan': {
name: 'Add',
screen: StackNavigator(Stack.Add, {
headerMode: 'none'
}),
navigationOptions: ({ navigation }) => ({
drawerIcon: AddMenuIcon(navigation)
})
}
}
const CustomDrawerContentComponent = props => (
<SafeAreaView style={{ flex: 1, backgroundColor: '#3f3f3f', color: 'white' }}>
<View>
<Image
style={{
marginLeft: 20,
marginBottom: 0,
marginTop: 0,
width: 100,
height: 100,
resizeMode: 'contain'
}}
square
source={require('../../images/logo_v_white.png')}
/>
</View>
<DrawerItems {...props} />
</SafeAreaView>
)
const Menu = StackNavigator(
{
Drawer: {
name: 'Drawer',
screen: DrawerNavigator(DrawerRoutes, {
initialRouteName: 'Login',
drawerPosition: 'left',
contentComponent: CustomDrawerContentComponent,
contentOptions: {
activeTintColor: '#27a562',
inactiveTintColor: 'white',
activeBackgroundColor: '#3a3a3a'
}
})
}
},
{
headerMode: 'none',
initialRouteName: 'Drawer'
}
)
export default Menu
Here I render the StackNavigator which is Menu in my app component:
import React, { Component } from 'react'
import Menu from './menu/view'
import Props from 'prop-types'
import { Container } from 'native-base'
import { updateAlertModalIsOpen } from './formControls/alertModal/action'
import AlertModalComponent from './formControls/alertModal/view'
import UserLoginModal from './user/login/loginModal/view'
class Vepo extends Component {
componentDidMount() {
const { store } = this.context
this.unsubscribe = store.subscribe(() => {})
store.dispatch(this.props.fetchUserGeoCoords())
store.dispatch(this.props.fetchSearchQueryPageCategories())
store.dispatch(this.props.fetchCategories())
}
componentWillUnmount() {
this.unsubscribe()
}
render(): Object {
return (
<Container>
<Menu store={this.context} />
<AlertModalComponent
yesClicked={() => {
updateAlertModalIsOpen(false)
}}
/>
<UserLoginModal />
</Container>
)
}
}
Vepo.contextTypes = {
store: Props.object
}
export default Vepo
and my root component:
export const store = createStore(
rootReducer,
vepo,
composeWithDevTools(applyMiddleware(createEpicMiddleware(rootEpic)))
)
import NavigationService from './navigationService'
export const App = () => (
<Provider store={store}>
<Vepo
fetchUserGeoCoords={fetchUserGeoCoords}
fetchSearchQueryPageCategories={fetchSearchQueryPageCategories}
fetchCategories={fetchCategories}
/>
</Provider>
)
AppRegistry.registerComponent('vepo', () => App)
I have changed my Vepo component to this to implement the answer by vahissan:
import React, { Component } from 'react'
import Menu from './menu/view'
import Props from 'prop-types'
import { Container } from 'native-base'
import { updateAlertModalIsOpen } from './formControls/alertModal/action'
import AlertModalComponent from './formControls/alertModal/view'
import UserLoginModal from './user/login/loginModal/view'
import NavigationService from './navigationService'
class Vepo extends Component {
componentDidMount() {
const { store } = this.context
this.unsubscribe = store.subscribe(() => {})
store.dispatch(this.props.fetchUserGeoCoords())
store.dispatch(this.props.fetchSearchQueryPageCategories())
store.dispatch(this.props.fetchCategories())
}
componentWillUnmount() {
this.unsubscribe()
}
render(): Object {
return (
<Container>
<Menu
store={this.context}
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef)
}}>
<AlertModalComponent
yesClicked={() => {
updateAlertModalIsOpen(false)
}}
/>
</Menu>
<UserLoginModal />
</Container>
)
}
}
Vepo.contextTypes = {
store: Props.object
}
export default Vepo
No errors, but the alertModal no longer displays
In react-navigation, the main StackNavigator creates a context provider and the navigation prop will be made available to any component below its level in the component tree if they use the context consumer.
Two ways to access the navigation prop using context consumer is to either add the component to the StackNavigator, or use the withNavigation function. However because of how React's context API works, any component that uses withNavigation function must be below the StackNavigator in the component tree.
If you still want to access the navigation prop regardless of the position in component tree, you will have to store the ref to the StackNavigator in a module. Following guide from react-navigation will help you do that https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html
If you are using react-navigation version 5, use useNavigation hook with a functional component. This hook injects the navigation object into the functional component. Here is the link to the docs:
https://reactnavigation.org/docs/use-navigation/
Vahissan's answer is correct but I could not get it working because of various differences in my code from https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html like my stackNavigator not being a component, it is just an object.
What I managed to do was get the AlertModal component to be a child of the stackNavigator and thus receive the navigation prop by adding it to my StackNavigator's ContentComponent. The code is as above but int the CustomDrawerContentComponent just making it like this:
const CustomDrawerContentComponent = props => (
<SafeAreaView style={{ flex: 1, backgroundColor: '#3f3f3f', color: 'white' }}>
<View>
<Image
style={{
marginLeft: 20,
marginBottom: 0,
marginTop: 0,
width: 100,
height: 100,
resizeMode: 'contain'
}}
square
source={require('../../images/logo_v_white.png')}
/>
</View>
<DrawerItems {...props} />
<AlertModalComponent
yesClicked={() => {
updateAlertModalIsOpen(false)
}}
/>
</SafeAreaView>
)
For anyone who might be interested, you need to npm install #react-navigation/native #react-navigation/compat #react-navigation/stack for withNavigation to work in the recent version

React Navigation StackNavigator not appearing when used inside another view

I'm attempting to use a React Navigation StackNavigator for a process that includes a static component at the top of the page and varying components at the bottom. The code I'm using is:
const Navigator = StackNavigator ({
splash: Splash,
prompt: Prompt,
pinCheck: PinCheck
}, {
initialRouteName: 'splash'
});
export default class Login extends React.Component
{
constructor (props)
{
super (props);
// code to set up animation state
}
componentDidMount()
{
// code to set up animation
}
finish_ (state)
{
this.props.navigation.navigate ('main', state);
}
render()
{
const screen = Dimensions.get('screen');
return (
<KeyboardAvoidingView style={Global.styles.verticalFill} ref={this.saveContainerRef}>
<ScrollView style={{flex: 1}} contentContainerStyle={{justifyContent: 'space-between'}}>
<Animated.View style={{opacity:this.state.fade1,alignItems:'center'}} >
<Image
style={{width:screen.width * 0.6,height: screen.height*0.55}}
source={imgLogo}
resizeMode='contain'
/>
<Navigator />
</Animated.View>
</ScrollView>
</KeyboardAvoidingView>
);
}
}
When I run this, however, my initial route component is not shown. It works correctly if I swap <Navigator/> to <Splash/> however, so the component itself definitely works in this context.
Any ideas what's wrong?
There is a problem in your navigation setup.
All the routes in the StackNavigator must declare a screen
as mentioned in the docs
const Navigator = StackNavigator ({
splash: {
screen: splash
},
prompt: {
screen: prompt
},
pinCheck: {
screen: pinCheck
}
}, {
initialRouteName: 'splash'
})

React Navigation autoFocus when using TabNavigator

In react-navigation, what is the best way to handle a tab that has a form with an autoFocus input that automatically pulls up the keyboard?
When the Navigator initializes all the screens, it automatically displays the keyboard even though the screen without the autoFocus element is showing first.
I want it to open the keyboard when I'm on the tab with the form, but close it when I leave that view.
Here is an example (and an associated Gist):
App.js
const AppNavigator = TabNavigator( {
listView: { screen: TheListView },
formView: { screen: TheFormView }
} )
TheFormView.js
const TheFormView = () => {
return (
<View style={{ marginTop: 50 }}>
<TextInput
autoFocus={ true }
keyboardType="default"
placeholder="Blah"
/>
</View>
)
}
TheListView.js
const TheListView = () => {
return (
<View style={{ marginTop: 50 }}>
<Text>ListView</Text>
</View>
)
}
You should use lazy on TabNavigator config: https://github.com/react-community/react-navigation/blob/master/docs/api/navigators/TabNavigator.md#tabnavigatorconfig
This prevents the screen from being initialised before it's viewed.
Also consider having some kind of state management or look for Custom Navigators (https://reactnavigation.org/docs/navigators/custom) for setting the autoFocus prop as true only when TheFormView is navigated to.
This answer was out of date for me as of April 2020, but this worked for me:
import { useFocusEffect, } from "#react-navigation/native"
import React, { useEffect, useState, } from "react"
...
const CreateProfileScreen = ({ navigation, }) => {
const [safeToOpenKeyboard, setSafeToOpenKeyBoard] = useState(false)
...
useFocusEffect(
React.useCallback(() => {
console.log("Navigated to CreateProfileScreen")
setSafeToOpenKeyBoard(true)
return () => {
console.log("Navigated away from CreateProfileScreen")
setSafeToOpenKeyBoard(false)
}
}, [])
)
...
return (<TextInput autoFocus={safeToOpenKeyboard}/>)
}

How to access the react-navgiation inside of a functional component or class component which doesnt have access to this.props.navigation?

Im doing this inside the react native platform using expo.
I want to display the list of items ( ListItems.js) All_Employees_screen.js . These items are being rendered via a functional component, I want to have a onRowPress() handler to so that upon clicking it i can navigate it to another view, but I dont know how to do it on react-navigation ?
Or since the new functional component can be a class component( this would be better ) how can i access the navigation thing inside it ?
AllProperties.js
import _ from 'lodash';
import React, {
Component
} from 'react';
import {
Button,
ListView,
ScrollView
} from 'react-native';
import ListItem from './ListItem';
import { connect } from 'react-redux';
import { propertiesFetch } from '../../actions';
// import { FormLabel, FormInput } from 'react-native-elements'
class AllPropertiesScreen extends React.Component {
componentWillMount(){
this.props.propertiesFetch();
this.createDataSource(this.props);
}
// we do this componentWillMount & componentWillReceiveProps (nextProps) thing twice, coz once the component is
// loaded it loads all teh values but when user hits another view like Create property, The Property data still exists
// in the global state object,
// we could move all the dc dataSource code into componentWillReceiveProps but its actually gonna benefit us
// if we make sure that we try to build our data source both when the component first loads up
// & when second time after we go back and forth other compoennts.
componentWillReceiveProps(nextProps){
// nextProps are the next set of props that this component will be rendered with
// this.props is still the old set of props
this.createDataSource(nextProps);
}
createDataSource({ properties }){
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.dataSource = ds.cloneWithRows(properties);
}
static navigationOptions = ({ navigation }) => {
const {state, setParams} = navigation;
return {
title: 'All Emplooyee',
headerRight: (
<Button
title='Add'
// onPress={() => setParams({ mode: isInfo ? 'none' : 'info'})}
onPress={() => navigation.navigate('createProperty')
}
/>
),
};
};
goBack(){
console.log('65 - go Back clicked');
}
renderRow(property){
// console.log('67-AllPropertiesScreen =', property);
return <ListItem property={property}
onPress={() => { console.log('65 - go Back clicked') }}
/>;
}
render() {
console.log('72-AllPropertiesScreen this.props', this.props );
return(
<ListView
enableEmptySections
dataSource={this.dataSource}
renderRow={this.renderRow}
/>
);
}
}
const mapStateToProps = state => {
console.log('83 - AllPropertiesScreen state. properties', state );
const properties = _.map(state.properties, (val, uid ) => {
return { ...val, uid }; // { shift: 'Monday'}
});
return { properties };
};
export default connect(mapStateToProps, {propertiesFetch}) (AllPropertiesScreen);
ListItem.js
import React, { Component } from 'react';
import { Text, TouchableWithoutFeedback, View } from 'react-native';
class ListItem extends Component {
// onRowPress(){
// Actions.employeeEdit({ employee: this.props.employee });
// }
render(){
const { agent_name, cell, address } = this.props.property;
console.log('14- ListItem ', this.props);
return (
<View>
<CardSection>
<Text style={styles.titleStyle}>
name
</Text>
<Text style={styles.titleStyle}>
cell
</Text>
<Text style={styles.titleStyle}>
address
</Text>
</CardSection>
</View>
);
}
}
const styles = {
titleStyle: {
fontSize: 18,
paddingLeft: 15
}
}
export default ListItem;
//
main.js ( this is where I have all the navigation paths hookedup.
class App extends React.Component {
render() {
const MainNavigator = TabNavigator({
// auth: { screen : AuthScreen },
// review: { screen: ReviewScreen },
// signup: { screen : SignupScreen },
followup: { screen: FollowupScreen }, welcome: { screen : WelcomeScreen },
auth: { screen : AuthScreen },
signup: { screen : SignupScreen },
main: {
screen: TabNavigator ({
followup: { screen: FollowupScreen },
map: { screen: MapScreen },
deck: { screen: DeckScreen },
settings : {
screen: StackNavigator ({
settings: { screen: SettingsScreen },
// settings: { screen: SettingsScreen },
UserProfile: { screen: UserProfileScreen },
HelpSupport: { screen: HelpSupportScreen },
Notifications: { screen: NotificationsScreen },
Signout: { screen: SignoutScreen } // not working, Navigation object not accessible inside the component
}) //screen: StackNavigator ({
},
followup : {
screen: StackNavigator ({
followup: { screen: FollowupScreen },
allProperties: { screen: AllPropertiesScreen },
createProperty: { screen: PropertyCreateScreen },
Red: { screen: RedPriorityScreen }, // not working, Navigation object not accessible inside the component
GreyPriority: { screen: GreyPriorityScreen },
}) //screen: StackNavigator ({
},
draw: {
screen: DrawerNavigator ({
drawin: { screen: DrawScreen },
}) //screen: StackNavigator ({
}
}) //screen: TabNavigator
}
}, {
navigationOptions: {
tabBarVisible: false
},
lazy: true
});
return (
<Provider store={store}>
<View style={styles.container}>
<MainNavigator />
</View>
</Provider>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
// alignItems: 'center',
justifyContent: 'center',
},
});
Expo.registerRootComponent(App);
Solution suggested by #Matt but as soon as I put the navigation={this.props.navigation} it complains. undefined is not an object ( evaluating this.props.navigation )
renderRow(property){
return (
<ListItem
property={property}
navigation={this.props.navigation}
onPress={() => {
console.log( '70-on Press inside renderRow ');
}}/>
);
}
If the component is not a screen you have to import the navigation.
Try this:
import React from 'react';
import { Button } 'react-native';
import { withNavigation } from 'react-navigation';
class MyBackButton extends React.Component {
render() {
return <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />;
}
}
// withNavigation returns a component that wraps MyBackButton and passes in the
// navigation prop
export default withNavigation(MyBackButton);
For more info check out
https://reactnavigation.org/docs/connecting-navigation-prop.html
This answer was written for old version of react-navigation V1
I had the same exact problem, and I found out that this.props.navigation is injected only in components that are registered as screen in StackNavigator or TabbNavigator.
but in general you can use navigate from NavigationActions class (source here https://v1.reactnavigation.org/docs/navigation-actions.html#navigate)
note: NavigationActions.navigate receives parameters in different way but works the same way.
so this working for me
import { NavigationActions } from 'react-navigation';
let {navigate} = NavigationActions;
renderRow(property) {
return (
<ListItem
property={property}
onPress={() => { navigate({
routeName: 'OtherRoute'
});
}}/>
);
}
<MyComponent navigation={this.props.navigation}/>
Main problem is here. You didn't define your prop navigation in component. You should add this.
Here's how you can use navigation.navigate inside a functional component:
import { Text, TouchableHighlight } from 'react-native';
const MyComponent = ({ navigation }) => (
<TouchableHighlight
onPress={() => navigation.navigate('OtherRoute')}
underlayColor="blue"/>
<Text>Click to Navigate!</Text>
</TouchableHighlight>
);
export default MyComponent;
When you render MyComponent, you will need to pass navigation as a prop. For example, assume HomeContainer is a screen component:
import React from 'react';
import MyComponent from './MyComponent';
export default HomeContainer extends React.Component {
render() {
return (
<MyComponent navigation={this.props.navigation}/>
);
}
}
Change your renderRow method to the following:
renderRow(property) {
return (
<ListItem
property={property}
onPress={() => { this.props.navigation.navigate('OtherRoute'); }}/>
);
}
where 'OtherRoute' is the name of the route you want to navigate to for that row.