Building an app using react-navigation. I have a parent component that pulls from firebase and renders data in a listview. The listview render component 'ListName' has an onRowPress function but this.props.navigation.navigate comes up undefined because navigation is not in that child component's state.
Ive tried multiple ways of passing in navigation prop to the child and also importing navigation from react-navigation within the child. Nothing works.
Thanks!
Here is my rootStackNavigator:
const RootStackNavigator = StackNavigator(
{
Login: { screen: LoginScreen },
Main: { screen: MainTabNavigator },
Feedback: { screen: ProvideInstanceScreen }
},
{
navigationOptions: () => ({
//headerTitleStyle: {
//fontWeight: 'normal',
tabBarVisible: false,
header: null
//},
}),
}
);
Here is my Parent Component (which has navigation.navigate in its state)
import React from 'react';
import { ListView, StyleSheet, Text, Image } from 'react-native';
import { connect } from 'react-redux';
import _ from 'lodash';
import { MainButton, GenSection } from '../components/common';
import { namesFetch } from '../actions';
import ListName from '../components/ListName.js';
class ProvideScreen extends React.Component {
static navigationOptions = {
header: null,
};
componentWillMount() {
//console.log('HOME HOME HOME PRINT', this.props)
this.props.namesFetch();
this.createDataSource(this.props);
}
componentDidMount() {
console.log('PROVIDE PROPS PRINT', this.props)
this.createDataSource(this.props);
}
componentWillReceiveProps(nextProps) {
//nextProps are next set of props component is rendered with and this.props is still old props
console.log('NEXT PROPS', nextProps)
this.createDataSource(nextProps);
}
createDataSource({ names }) {
var namesArray = names.map(function(a) {return [a.name, a.uid];});
//console.log('NAMES ARRAY PRINT', namesArray)
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.dataSource = ds.cloneWithRows(namesArray);
}
renderRow(user) {
return <ListName name={user[0]} />;
}
render() {
return (
<Image
source={require('../components/images/mainBG.png')}
style={styles.containerStyle}>
<Text style={styles.textStyle}>
Provide Feedback
</Text>
<GenSection style={{paddingTop: 8}} />
<ListView
enableEmptySections
dataSource={this.dataSource}
renderRow={this.renderRow}
removeClippedSubviews={false}
/>
</Image>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 15,
backgroundColor: '#fff',
},
containerStyle: {
flex: 1,
width: undefined,
height: undefined,
backgroundColor:'transparent'
},
textStyle:
{
paddingTop: 20,
paddingLeft: 12,
fontSize: 32,
fontWeight: '200',
color: '#597abc'
}
});
const mapStateToProps = state => {
//console.log('STATE PRINT', state.feedbackInput)
const names = _.map(state.feedbackInput, (val) => {
return { ...val};
});
//console.log('NAMES PRINT', names)
return { names };
}; //this is lodash .map iterates over key value pairs and run function which assigns data to groups array
export default connect(mapStateToProps, { namesFetch })(ProvideScreen);
Here is my child component (which does not have navigation.navigate in state):
import React, { Component } from 'react';
import { Text, TouchableWithoutFeedback, View } from 'react-native';
import { connect } from 'react-redux';
import { ListButton } from './common';
class ListName extends Component {
onRowPress() {
console.log('ON ROW PRESS PRINT', this.props)
this.props.navigation.navigate('Feedback', this.props);
}
componentDidMount() {
//console.log('LIST NAME LIST NAME PRINT', this.props)
}
render() {
const name = this.props.name;
//console.log('LISTNAME PRINT', name)
return (
<TouchableWithoutFeedback onPress={this.onRowPress.bind(this)}>
<View>
<ListButton>
<Text style={styles.titleStyle}>
{name}
</Text>
</ListButton>
</View>
</TouchableWithoutFeedback>
);
}
}
const styles = {
titleStyle: {
alignSelf: 'center',
color: '#fff',
fontSize: 16,
fontWeight: '600',
}
};
const mapStateToProps = state => {
//console.log('NAMES PRINT', names)
return state
}; //this is lodash .map iterates over key value pairs and run function which assigns data to groups array
export default connect(mapStateToProps)(ListName);
Base on React Navigation: https://reactnavigation.org/docs/en/connecting-navigation-prop.html
You just need to import withNavigation into child component only.
import { withNavigation } from 'react-navigation';
then export:
export default withNavigation(<YourChildComponent>);
One way is to have a onPress handler in your ProvideScreen
component that is passed down to your list item component and thus in ProvideScreen
's onRowPress function, you will have access to this.props.navigation
.
In ProvideScreen
:
class ProvideScreen extends Component {
...
onRowPress(someRowData) {
this.props.navigation.navigate('Feedback', { someRowData });
}
...
renderRow(user) {
return <ListName name={user[0]} onRowPress={this.onRowPress} />;
}
}
In ListName
:
class ListName extends Component {
...
onRowPress() {
this.props.onRowPress(someData);
}
...
}
Of course, don't forget about binding the functions to this
scope when you are using event handlers.
e.g. in constructor:
this.onRowPress = this.onRowPress.bind(this);
An alternative define onRowPress
with an arrow functions:
onRowPress = () => {
this.props.navigation.navigate...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With