提取嵌套数据,未定义不是对象

时间:2019-05-25 21:37:29

标签: react-native expo

我正在尝试从API提取数据,但是我只能提取最高级别​​的数据。当我尝试访问嵌套在类别下的内容时,出现错误:undefined is not an object (evaluating 'this.state.data.order.name' )

从我读到的内容来看,状态可能是一个问题,但是我是本机反应的新手,我不确定该如何解决。

这是API结构

This is the API structure

 render(){
    const { data } = this.state;

 return(
  <ScrollView style={styles.containerxd}>
    <TouchableOpacity style={styles.textStyle}>
  <Image
     source={require('./images/burger.png')}

     style={styles.ImageIconStyle} />
    </TouchableOpacity>

 <View style={styles.white}>

        <View style={{flex:1, alignItems:'center', justifyContent:'center'}}> 

  <View style={styles.tabHeader}><Text style={styles.textHeader}>Scientific name</Text></View>
  <View style={styles.tabContent}><Text style={styles.textContent}>{this.state.data.scientific_name}</Text></View>

  <View style={styles.tabHeader}><Text style={styles.textHeader}>Common name</Text></View>
  <View style={styles.tabContent}><Text style={styles.textContent}>{this.state.data.common_name}</Text></View>

  <View style={styles.tabHeader}><Text style={styles.textHeader}>Moisture use</Text></View>
  <View style={styles.tabContent}><Text style={styles.textContent}>{this.state.data.order.name}</Text></View>

科学名称和通用名称显示得很好,但是每降低一个数据级别都会出现错误。

1 个答案:

答案 0 :(得分:1)

您需要验证数据。未定义订单时,执行order.name将破坏您的应用。改变

<View style={styles.tabContent}><Text style={styles.textContent}>{this.state.data.order.name}</Text></View>

const { data } = this.state;
const name = data && data.order && data.order.name || '';

// rest of the code here
<View style={styles.tabContent}><Text style={styles.textContent}>{name}</Text></View>

注意

始终验证您的数据。不要以为您将始终获得正确的数据。如果data.name为null或未定义,则在使用对象时总是要像对data那样进行验证,这可能会破坏您的应用程序。例如,给定以下对象。

const animal = {};

// throws an error, Cannot read property 'toLowerCase' of undefined
console.log(animal.name.toLowerCase())

为防止这种情况发生,我们需要检查属性是否存在,如下所示。

// checks if the name property exists console name, else assign a console log 'Lion'
console.log(animal.name && animal.name.toLowerCase() || 'Lion')

第二个选项

添加一个加载器,从api提取数据时显示Loading...文本,一旦请求完成,将加载器设置为false并显示您的数据。

fetchData = async () => {

  const res = await fetch(...)
  ...
  this.setState({ isLoading: false, data: response.data });
}

render() {

  return (
    <ScrollView style={styles.containerxd}>
      <TouchableOpacity style={styles.textStyle}>
        <Image
          source={require('./images/burger.png')}
          style={styles.ImageIconStyle}
        />
      </TouchableOpacity>

      {this.state.isLoading ? (
        <Text>Loading...</Text>
      ) : (
        <View style={styles.white}>
          <View
            style={{
              flex: 1,
              alignItems: 'center',
              justifyContent: 'center'
            }}
          >
            <View style={styles.tabHeader}>
              <Text style={styles.textHeader}>Scientific name</Text>
            </View>
            <View style={styles.tabContent}>
              <Text style={styles.textContent}>
                {this.state.data.scientific_name}
              </Text>
            </View>

            <View style={styles.tabHeader}>
              <Text style={styles.textHeader}>Common name</Text>
            </View>
            <View style={styles.tabContent}>
              <Text style={styles.textContent}>
                {this.state.data.common_name}
              </Text>
            </View>

            <View style={styles.tabHeader}>
              <Text style={styles.textHeader}>Moisture use</Text>
            </View>
            <View style={styles.tabContent}>
              <Text style={styles.textContent}>
                {this.state.data.order.name}
              </Text>
            </View>
          </View>
        </View>
      )}
    </ScrollView>
  );
}