尝试从嵌套对象中检索键/值后,“ TypeErroe:无法读取未定义的属性名称”

时间:2019-02-26 00:39:26

标签: react-native object async-await fetch state

我试图在react-native中获取一些数据,并将获取的数据存储在state变量中,以便可以在组件中的任何位置访问它们。这是代码:

export default class Result extends Component {
    state = {
        data: {}
    };

    async componentDidMount() {
        const that = this;
        const url = 'https://world.openfoodfacts.org/api/v0/product/8002270014901.json';
        let response = await fetch(url);
        if (response.status == 200) {
            let data = await response.json();
            this.setState({ data });
        }
    }

    ... some code ...

    render() {
      console.log(this.state.data.product);

    ...some more code ...
    }
}

我从另一本SOF文章的componentDidMount中获取了代码,以确保可以使用一些data。 当我尝试测试结果时,它与您在代码中看到的console.log完美配合。但是,如果我尝试在对象内深入一层(例如console.log(this.state.data.product.brands);,则会收到主题中提到的错误消息。为什么会这样呢?如何在继续操作之前确保整个对象都已“加载” ?

1 个答案:

答案 0 :(得分:1)

在这种情况下,我想到的是您在执行render方法之后收到响应。

您可能会问但是当我仅登录this.state.data.product时它如何工作?
好吧,在初始化状态时,您要定义它具有一个data对象,因此在这种情况下,代码不会中断,因为this.state.data.productundefined,但是当您尝试获取时现在更深一层,您正在尝试访问一个undefined值的属性,这会导致出现错误(无法读取未定义的属性 x )。

那我该怎么解决?

您必须在状态中存储一个布尔变量,将其命名为fetchingData,并将其默认值设置为true,所以现在您拥有了

state = {
  data: {},
  fetchingData: true
};

然后,在您的render方法上,验证它是否正在获取数据,或者是否已经收到服务器的响应,将其修改为:

render() {
  if(this.state.fetchingData) return <View><Text>Fetching data...</Text></View>
  console.log(this.state.data.product.brands);
  return(
    Whatever you want to do with the data...
  )
}

它的作用是当您仍在等待数据时,会显示一条Fetching data...消息,现在,当您收到数据时,还必须将fetchingData更改为false。

if (response.status == 200) {
  let data = await response.json();
  this.setState({
    data: data,
    fetchingData: false
  });
}