无法在react-navigation中读取undefined的属性'navigate'

时间:2018-04-15 04:52:20

标签: react-native react-navigation

我在我的Router.js中使用了import { StackNavigator } from 'react-navigation';

import { StackNavigator } from 'react-navigation';
import LoginForm from './components/LoginForm';
import EmployeeList from './components/EmployeeList';
import EmployeeCreate from './components/EmployeeCreate';

const RouterComponent = StackNavigator(
{
  LoginForm: {
    screen: LoginForm,
    navigationOptions: {
      title: 'Please Login'
    }
  },
  EmployeeList: {
    screen: EmployeeList,
  },
  EmployeeCreate: {
    screen: EmployeeCreate,
    navigationOptions: {
      title: 'Create Employee'
    }
  }
},
{
  initialRouteName: 'LoginForm',
}
);

export default RouterComponent;

当然我在App.js中使用它

import React from 'react';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import ReduxThunk from 'redux-thunk';
import reducers from './src/reducers';
import Router from './src/Router';

export default class App extends React.Component {
  render() {
    const store = createStore(reducers, {}, applyMiddleware(ReduxThunk));

    return (
      <Provider store={store}>
        <Router />
      </Provider>
    );
  }
}

我可以在this.props.navigation中使用LoginForm.js这样的功能:

  onButtonPress() {
    const { email, password, navigation } = this.props;

    this.props.loginUser({ email, password, navigation });
  }

我将导航传递给我的Action文件,我可以用它来导航另一个屏幕,如下所示:

const loginUserSuccess = (dispatch, user, navigation) => {
  dispatch({
    type: LOGIN_USER_SUCCESS,
    payload: user
  });
  //navigation is from LoginForm.js , navigate to EmployeeList is working
  navigation.navigate('EmployeeList');
};

现在我尝试在ListItem.js中使用this.props.navigation.navigate

我的ListItem位于EmployeeList.js

之下

这是我的EmployeeList.js

import _ from 'lodash';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { View, Text, Button, FlatList } from 'react-native';
import { employeesFetch } from '../actions';
import ListItem from './ListItem';

class EmployeeList extends Component {
  static navigationOptions = ({ navigation }) => ({
    title: 'EmployeeList',
    headerLeft: null,
    headerRight: <Button title="Add" onPress={() => navigation.navigate('EmployeeCreate')} />,
  });

  componentWillMount() {
    this.props.employeesFetch(); 
  }
  // Using ListItem over here
  renderRow(employee) {
    return <ListItem employee={employee} />;
  }

  render() {
    console.log(this.props);
    return (
      <FlatList
        data={this.props.employees}
        renderItem={this.renderRow}
        keyExtractor={employee => employee.uid}
      />
    );
  }
}

const mapStateToProps = state => {
  const employees = _.map(state.employees, (val, uid) => {
    return { ...val, uid };
  });

  return { employees };
};

export default connect(mapStateToProps, { employeesFetch })(EmployeeList);

这是我的问题在ListItem.js中使用this.props.navigation.navigate

import React, { Component } from 'react';
import { Text, View, TouchableWithoutFeedback } from 'react-native';
import { CardSection } from './common';

class ListItem extends Component {

  onRowPress() {
    this.props.navigation.navigate('EmployeeCreate');
  }

  render() {
    const { item } = this.props.employee;
    return (
      <TouchableWithoutFeedback onPress={this.onRowPress.bind(this)}>
        <View>
          <CardSection>
            <Text style={styles.titleSytle}>
              {item.name}
            </Text>
          </CardSection>
        </View>
      </TouchableWithoutFeedback>
    );
  }
}

const styles = {
  titleSytle: {
    fontSize: 18,
    paddingLeft: 15
  }
};

export default ListItem;

我可以在我的LoginForm.js中使用this.props.navigation,我无法弄清楚为什么我在ListItem.js中使用它导航是未定义的?

任何帮助将不胜感激。提前谢谢。

3 个答案:

答案 0 :(得分:1)

文件EmployeeList.js中的

将导航作为支持传递给ListItem。

renderRow(employee) {
  return <ListItem employee={employee} navigation={this.props.navigation} />;
}

现在,您应该可以使用this.props.navigation内的ListItem.js来访问导航。

  

只是一个观察,永远不会将方法绑定到渲染中的上下文   函数,因为它被重复调用,并将创建一个新的实例   每一次。如下所示更改ListItem.js

class ListItem extends Component {

  constructor(props) {
    super(props);
    this.onRowPress = this.onRowPress.bind(this);  // here we bind it
  }

  onRowPress() {
    this.props.navigation && this.props.navigation.navigate('EmployeeCreate');
  }

  render() {
    const { item } = this.props.employee;
    return (
      <TouchableWithoutFeedback onPress={this.onRowPress}>
        <View>
          <CardSection>
            <Text style={styles.titleSytle}>
              {item.name}
            </Text>
          </CardSection>
        </View>
      </TouchableWithoutFeedback>
    );
  }
}

答案 1 :(得分:0)

使用withNavigation。在您的ListItem.js文件中,添加import { withNavigation } from ‘react-navigation’;并将export default ListItem;替换为export default withNavigation(ListItem);

答案 2 :(得分:0)

这就是我所做的(使用ES6内置的最新React):

从中重构类代码:

export default class MyComponent extends React.Component {
   // content & code
}

看起来像这样:

import { withNavigation } from 'react-navigation';

class MyComponent extends React.Component {
   // content & code
}
export default withNavigation(MyComponent);

根据文档(withNavigation):

“ withNavigation是一个更高阶的组件,它将导航道具传递到包装的组件中。”