开发者问题收集

无法读取 react-navigation 中未定义的属性“navigate”

2018-04-15
6903

我已经在 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>
    );
  }
}

我可以在我的 LoginForm.js 中使用 this.props.navigation ,如下所示:

  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

我的 ListItemEmployeeList.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个回答

在文件 EmployeeList.js 中将导航作为 prop 传递给 ListItem。

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

现在您应该能够使用 ListItem.js 中的 this.props.navigation 访问导航。

Just an observation, never bind methods to context inside the render function as it is called repeatedly and a new instance will be created each time. Change your ListItem.js as below.

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>
    );
  }
}
Rishabh Bhatia
2018-04-15

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

Mher
2019-06-27

这是我所做的(使用最新的 React Native 和 ES6):

从这里重构类代码:

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 是一个高阶组件,它将导航 prop 传递到包装的组件中。”

Trevor
2019-12-12