在reactjs中渲染嵌套对象

时间:2019-03-28 09:18:50

标签: javascript reactjs

我很难将嵌套对象呈现到reactjs页面上

import React, { Component } from "react";
import Toolpanel from "./Todopanel";
import Toollist from "./Toollist";
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      users: [],
      city: "Auckland",
      cityWeather: {}
    };
    this.updateUser = this.updateUser.bind(this);
  }

  updateUser(entry) {
    console.log(entry);
    let item = {
      text: entry,
      key: Date.now()
    };
    this.setState(prevstate => {
      return {
        users: prevstate.users.concat(item)
      };
    });
  }

  componentDidMount() {
    let apiId = "***************************";
    let city = this.state.city;
    let ApiString =
      "http://api.openweathermap.org/data/2.5/weather?q=" +
      city +
      "&APPID=" +
      apiId;
    fetch(ApiString)
      .then(results => results.json())
      .then(data => this.setState({ cityWeather: data }));
  }

  render() {
    let test = this.state.cityWeather;

    return (
      <div>
        <Toolpanel parentUpdate={this.updateUser} />

        <div>wind speed : {test.wind.speed} </div>
      </div>
    );
  }
}

export default App;

我已经添加了从天气API接收到的JSON文件

//Json file
{
  "coord": { "lon": 174.77, "lat": -36.85 },
  "weather": [
    {
      "id": 804,
      "main": "Clouds",
      "description": "overcast clouds",
      "icon": "04n"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 293.7,
    "pressure": 1018,
    "humidity": 77,
    "temp_min": 293.15,
    "temp_max": 294.26
  },
  "visibility": 10000,
  "wind": { "speed": 5.1, "deg": 360 },
  "clouds": { "all": 92 },
  "dt": 1553672420,
  "sys": {
    "type": 1,
    "id": 7345,
    "message": 0.0043,
    "country": "NZ",
    "sunrise": 1553624951,
    "sunset": 1553667823
  },
  "id": 2193733,
  "name": "Auckland",
  "cod": 200
}

我正在尝试将JSON的风速呈现给我的页面..但是向我抛出一条错误消息,提示“ TypeError:无法读取未定义的属性'speed'” ...我对ReactJ相当陌生。

5 个答案:

答案 0 :(得分:3)

如果您看代码,下面是事件的顺序:

  1. 已创建组件,即名为constructor
  2. 已安装组件,即称为componentDidMount
  3. componentDidMount启动async请求以获取数据,然后将其解析并设置为状态。
  4. render方法尝试从状态读取数据。

现在,由于#3中的请求是异步请求,因此在第一次调用render方法时,它可能未及时完成。

因此,您需要检查您的请求是否已完成或失败或正在运行。

您可以使用它conditionally render渲染方法中的内容。

推荐阅读 async rendering with examples of when data is fetched from an external resource

上的官方reactjs博客条目

答案 1 :(得分:2)

您没有错。您收到的错误是因为您正在执行的抓取操作需要花费一些时间,并且渲染首先执行而没有填充数据。

因此,它第一次在您的渲染方法中获得test = {}的值。因此test.wind.speed将引发错误。

相反,显示某种加载状态或仅显示return null,直到执行调用为止:

render() {
    let test = this.state.cityWeather;
    if (!test) {
        return 'Loading...';
    }

    ....
} 

答案 2 :(得分:1)

由于fetch是异步调用,因此您访问属性的速度太快,这会花费一些时间,但是您的render会在此之前触发。

像这样使用它

{ test && <div>wind speed : {test.wind.speed} </div>}

答案 3 :(得分:1)

最初,您的测试将为null,因为您尚未收到来自API的任何响应,因此您应在使用前检查变量是否存在。因此,只需像使用它之前检查它是否存在:

render() {
    let test = this.state.cityWeather;

    return (
      <div>
        <Toolpanel parentUpdate={this.updateUser} />

        <div>wind speed : {test && test.wind && test.wind.speed ? test.wind.speed : ''} </div>
      </div>
    );
  }

答案 4 :(得分:1)

由于您没有发布ToolPanel组件实现,因此我可能是错的(我缺少一些信息)。但是,我也很确定您的问题没有loading变量。

基本上,第一次调用render()方法时,您有this.state.cityWeather是一个空对象{};那是因为您获取了componentDidMount()中的数据。因此,第一次调用render()时,this.state.cityWeather为空,您无法访问this.state.cityWeather.wind.speed,因为您在wind中没有属性this.state.cityWeather! / p>

因此,通常,执行此操作的常用方法是在状态中添加属性loading,然后在true中将其设置为constructor。然后,在提取的回调中,在this.state.cityWeather中设置数据的同时,还将loading设置为true
最后,在render()方法中编写了条件渲染:如果this.state.loading === true,则打印一个简单的段落,如<p>I'm retrieving info!</p>,否则,如果this.state.loading === false,则可以渲染想要。