使用react-navigation构建应用。我有一个父组件,它从firebase中提取并在listview中呈现数据。 listview呈现组件' ListName'有一个onRowPress函数,但this.props.navigation.navigate未定义,因为导航不在该子组件的状态。
我尝试过多种方式将导航道具传递给孩子,并从孩子内部的反应导航中导入导航。什么都行不通。
谢谢!
这是我的rootStackNavigator:
const RootStackNavigator = StackNavigator(
{
Login: { screen: LoginScreen },
Main: { screen: MainTabNavigator },
Feedback: { screen: ProvideInstanceScreen }
},
{
navigationOptions: () => ({
//headerTitleStyle: {
//fontWeight: 'normal',
tabBarVisible: false,
header: null
//},
}),
}
);
这是我的父组件(其状态为navigation.navigate)
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);
这是我的子组件(在状态中没有navigation.navigate):
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);
答案 0 :(得分:6)
基于React导航: https://reactnavigation.org/docs/en/connecting-navigation-prop.html
您只需要将withNavigation导入子组件。
import { withNavigation } from 'react-navigation';
然后导出:
export default withNavigation(<YourChildComponent>);
答案 1 :(得分:4)
一种方法是在ProvideScreen
组件中有一个onPress处理程序,该处理程序传递给列表项组件,因此在ProvideScreen
的onRowPress函数中,您将可以访问{{1} }。
在this.props.navigation
:
ProvideScreen
在class ProvideScreen extends Component {
...
onRowPress(someRowData) {
this.props.navigation.navigate('Feedback', { someRowData });
}
...
renderRow(user) {
return <ListName name={user[0]} onRowPress={this.onRowPress} />;
}
}
:
ListName
当然,在使用事件处理程序时,不要忘记将函数绑定到class ListName extends Component {
...
onRowPress() {
this.props.onRowPress(someData);
}
...
}
范围。
例如在构造函数中:
this
使用箭头函数替代定义this.onRowPress = this.onRowPress.bind(this);
:
onRowPress
答案 2 :(得分:1)
传递所有道具
表格
{...this.props}
<Form>
是我的子组件
其他方面。
import { withNavigation } from 'react-navigation';
然后结束
export default withNavigation(<ChildComponentName>);
答案 3 :(得分:1)
您还可以通过以下操作将导航道具直接从父母传递给孩子:
renderRow(user) {
return <ListName name={user[0]} navigation={this.props.navigation}/>;
}
这将允许您在ListName中使用react-navigation的navigation方法。
此页面上的信息:https://reactnavigation.org/docs/en/connecting-navigation-prop.html
答案 4 :(得分:1)
我只是从父母那里添加了这个道具就可以了:
<AppFooter navigation={this.props.navigation} />
答案 5 :(得分:0)
import {withNavigation} from 'react-navigation';
class Parent extends Component{
<Child {...this.props}/>
}
class Child extends Component {
<TouchableOpacity onPress={()=>this.props.navigation.navigate("Screen")}>
<V><T>
{PRESS ME}
</V></T>
</TouchableOpacity>
}
export default withNavigation(Parent);