首页 > 解决方案 > ERROR TypeError: undefined is not an object (evalating 'this.props.navigation.navigate') when import my component in child

问题描述

我已经创建了一个折叠菜单组件并将其导入到另一个组件但屏幕无法导航。它显示错误TypeError: undefined is not an object (evaluation 'this.props.navigation.navigate')。我无法通过标签名称导航我的屏幕。

折叠菜单代码

import React, {useState, useEffect} from 'react';
import {
  View,
  StyleSheet,
  Text,
  LayoutAnimation,
  TouchableOpacity,
} from 'react-native';

import Font from '../constant/fonts';
import Color from '../constant/colors';
import fontF from '../styles/fontfamily';
import Icon from '../styles/icons';

import {heightToDp, widthToDp} from '../constant/utils';
import Size from '../constant/sizes';
import Card from './Cards/card';
import {Divider} from 'react-native-elements';
class CollapseMenu extends React.Component {
  componentDidMount() {
    console.log('navigation', this.props);
  }

  constructor(props) {
    super(props);

    this.state = {
      expanded: false,
    };
    this.handleCollapse = this.handleCollapse.bind(this);
  }

  handleCollapse() {
    const {expanded} = this.state;
    this.setState({expanded: !expanded});
  }
  handleRoute(label) {
    console.log(this.props);
    this.props.navigation.navigate(label);
  }

  render() {
    const {expanded} = this.state;
    return (
      <View>
        <TouchableOpacity onPress={this.handleCollapse}>
          <View style={styles.mainContainer}>
            <View style={[styles.sidebarDesign]}>
              <View style={styles.barIcon}>
                <Icon.SimpleLineIcons name={this.props.item.icon} size={20} />
              </View>
              <View style={styles.barLabel}>
                <Text style={[styles.labelStyle]}>
                  {this.props.item.title.toUpperCase()}
                </Text>
              </View>
              <View style={styles.barIcon}>
                <Icon.SimpleLineIcons
                  name={expanded ? 'arrow-up' : 'arrow-down'}
                  size={20}
                  color={Color.grayDark}
                />
              </View>
            </View>
          </View>
        </TouchableOpacity>

        {this.props.item.subarr.map((child, j) => (
          <View>
            {expanded ? (
              <TouchableOpacity
                onPress={this.handleRoute.bind(this, child.label)}>
                <View style={[styles.sidebarDesign]}>
                  <View style={styles.barIcon}>
                    {/* <Icon.FontAwesome
                            name={r.icon}
                            size={20}
                            color={Color.gray}
                          /> */}
                  </View>
                  <View style={styles.barLabel}>
                    <Text style={[styles.labelStyle]}>
                      {child.label.toUpperCase()}
                    </Text>
                  </View>
                  <View style={styles.barIcon}>{/* <Text>icon</Text> */}</View>
                </View>
              </TouchableOpacity>
            ) : null}
          </View>
        ))}
      </View>
    );
  }
}

});

export default CollapseMenu;

并通过传递以下数据来使用此组件:

 <CollapseMenu item={data}/>

标签: javascriptreactjsreact-native

解决方案


使用 react-navigation v5,只有我们必须从嵌套的子/非路由组件导航的 api 是useNavigate只能在函数组件中使用的钩子。

根据docs,在类组件中使用的解决方法是创建一个包装函数组件。

import React, {useState, useEffect} from 'react';
import {
  View,
  StyleSheet,
  Text,
  LayoutAnimation,
  TouchableOpacity,
} from 'react-native';

import Font from '../constant/fonts';
import Color from '../constant/colors';
import fontF from '../styles/fontfamily';
import Icon from '../styles/icons';

import {heightToDp, widthToDp} from '../constant/utils';
import Size from '../constant/sizes';
import Card from './Cards/card';
import {Divider} from 'react-native-elements';
class CollapseMenu extends React.Component {
  componentDidMount() {
    console.log('navigation', this.props);
  }

  constructor(props) {
    super(props);

    this.state = {
      expanded: false,
    };
    this.handleCollapse = this.handleCollapse.bind(this);
  }

  handleCollapse() {
    const {expanded} = this.state;
    this.setState({expanded: !expanded});
  }
  handleRoute(label) {
    console.log(this.props);
    this.props.navigation.navigate(label);
  }

  render() {
    const {expanded} = this.state;
    return (
      <View>
        <TouchableOpacity onPress={this.handleCollapse}>
          <View style={styles.mainContainer}>
            <View style={[styles.sidebarDesign]}>
              <View style={styles.barIcon}>
                <Icon.SimpleLineIcons name={this.props.item.icon} size={20} />
              </View>
              <View style={styles.barLabel}>
                <Text style={[styles.labelStyle]}>
                  {this.props.item.title.toUpperCase()}
                </Text>
              </View>
              <View style={styles.barIcon}>
                <Icon.SimpleLineIcons
                  name={expanded ? 'arrow-up' : 'arrow-down'}
                  size={20}
                  color={Color.grayDark}
                />
              </View>
            </View>
          </View>
        </TouchableOpacity>

        {this.props.item.subarr.map((child, j) => (
          <View>
            {expanded ? (
              <TouchableOpacity
                onPress={this.handleRoute.bind(this, child.label)}>
                <View style={[styles.sidebarDesign]}>
                  <View style={styles.barIcon}>
                    {/* <Icon.FontAwesome
                            name={r.icon}
                            size={20}
                            color={Color.gray}
                          /> */}
                  </View>
                  <View style={styles.barLabel}>
                    <Text style={[styles.labelStyle]}>
                      {child.label.toUpperCase()}
                    </Text>
                  </View>
                  <View style={styles.barIcon}>{/* <Text>icon</Text> */}</View>
                </View>
              </TouchableOpacity>
            ) : null}
          </View>
        ))}
      </View>
    );
  }
}

});

// Wrap and export 
function CollapseMenuWrapper(props) {
  const navigation = useNavigation();

  return <CollapseMenu {...props} navigation={navigation} />;
}
export default CollapseMenuWrapper;

推荐阅读