使用react-navigation构建应用程序。我有一个父组件,它从firebase中提取并在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);
基于React Navigation:https://reactnavigation.org/docs/en/connecting-navigation-prop.html
您只需将withNavigation导入子组件即可。
import { withNavigation } from 'react-navigation';
然后出口:
export default withNavigation(<YourChildComponent>);
一种方法是在你的ProvideScreen
组件中有一个onPress处理程序,它传递给你的列表项组件,因此在ProvideScreen
的onRowPress函数中,你将有权访问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
:
onRowPress = () => {
this.props.navigation.navigate...
}
我只是从父母那里添加这个道具并且它有效:
<AppFooter navigation={this.props.navigation} />
传递所有道具
形成
{...this.props}
这里<Form>
是我的孩子组成部分
除此以外。
import { withNavigation } from 'react-navigation';
然后到最后
export default withNavigation(<ChildComponentName>);
您还可以通过执行以下操作直接将导航道具从父项传递给子项:
renderRow(user) {
return <ListName name={user[0]} navigation={this.props.navigation}/>;
}
这将允许您在ListName中使用react-navigation的导航方法。
信息也来自此页面:https://reactnavigation.org/docs/en/connecting-navigation-prop.html
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);