将navigation.navigate传递给子组件

时间:2017-07-20 18:05:57

标签: react-native react-navigation

使用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);

6 个答案:

答案 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);