从api调用映射时检索嵌套的JSON对象

时间:2017-11-14 20:26:03

标签: javascript json reactjs typescript mapping

我正在努力将JSON映射到反应中的数据驱动渲染。完成我需要做的一些事情。我将要求嵌套JSON。 在尝试映射此数据时,我会继续运行无法映射的值。特别是当我尝试将嵌套值传递给插值div时(mapObject.object.value)

JSON

{"PositionComponent": [
        {
            "key": 0,
            "Elevation": {
                "positionValue": "1.11566",
                "id": 0
            }
        },
        {
            "key": 1,
            "Azimuth": {
                "positionValue": "1.145657",
                "id": 1
            }
        }
    ]
}

React Components:

import React, { Component } from 'react';
import '../HeaderBar/HeaderBar.css';
import 'whatwg-fetch';

type StatusBarProps = {};
type StatusBarState = {
    // tslint:disable-next-line:no-any
    positionStatus: any;
};

class StatusBar extends Component<StatusBarProps, StatusBarState> {
    constructor() {
        super();
        this.state = {
            positionStatus: []
        };
    }
    componentWillMount() {
        // maps azimuth and elevation for all objects
        fetch('http://localhost:5001/PositionComponent/').then(results => {
            return results.json();
        }).then(data => {
            let positionStatus = data.map((positioning) => {
                return (
                    <div className="temporary" key={positioning.key}>{positioning.Elevation.positionValue} : {positioning.Azimuth.positionValue}</div>
                );
            });
            this.setState({ positionStatus: positionStatus });
        });
    }
    render() {
        return (
            <div className="location">
                <div className="col-xs-12">
                    {this.state.positionStatus}
                </div>
            </div>
        );
    }
}

export default StatusBar;

为问题的上下文提供了相关的JSON,但是为了提高开发速度,它正在从JSON.server提供。似乎问题是我收到Object {key: 0, Elevation: Object } Object { key: 1, Azimuth: Object },我无法通过调用{positioning.Elevation.positionValue}进入对象本身。我的问题是,我将如何映射这个以便我可以将那些内部对象值与Elevation和Azimuth联系起来?

2 个答案:

答案 0 :(得分:2)

这里的主要问题是你在每个拥有你想要抓取的嵌套键的对象上有不同的键 您可以尝试有条件地访问它并检查现有的ElevationAzimuth并分别访问 这种方法的缺点是,当您添加新密钥时,应添加另一个条件。所以你可能想要一个更通用的方法。

您可以在.map中使用Object.entrieskeys,并为每个positionValue返回。如果某个键没有保留它,那么将评估未定义的map将忽略并且不会返回它 像这样:

Object.entries(positioning).map(([key, value]) => {
  return positioning[key].positionValue;
})

我会将渲染逻辑取出到另一种方法,并且不会将标记存储在状态中 您想要改变的另一件事是avoid the use of fetching or side effects in componentWillMount

以下是您的代码的运行示例(我没有使用fetch,因为我没有在服务器中提供您的数据)

const dataFromServer = [
  {
    key: 0,
    Elevation: {
      positionValue: "1.11566",
      id: 0
    }
  },
  {
    key: 1,
    Azimuth: {
      positionValue: "1.145657",
      id: 1
    }
  }
];

class StatusBar extends React.Component {
  constructor() {
    super();
    this.state = {
      positionStatus: []
    };
  }

  componentDidMount() {
    let positionStatus = dataFromServer;
    this.setState({ positionStatus: positionStatus });
  }

  renderPositionstatus = () => {
    const { positionStatus } = this.state;
    return (
      <div>
        {positionStatus.map(positioning => {
          return (
            <div className="temporary" key={positioning.key}>
              {Object.entries(positioning).map(([key, value]) => {
                return positioning[key].positionValue;
              })}
            </div>
          );
        })}
      </div>
    );
  };

  render() {
    return (
      <div className="location">
        <div className="col-xs-12">{this.renderPositionstatus()}</div>
      </div>
    );
  }
}

ReactDOM.render(<StatusBar />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

答案 1 :(得分:0)

认为这可能是JSON错误,但您正试图访问对象中的undefined道具。

这是您的data

[
  {
    "key": 0,
    "Elevation": {
      "positionValue": "1.11566",
      "id": 0
    }
  },
  {
    "key": 1,
    "Azimuth": {
      "positionValue": "1.145657",
      "id": 1
    }
  }
]

并非所有元素都有ElevationAzimuth道具。第一个只有Elevation而第二个有Azimuth

因此,这一行总会破裂:

{positioning.Elevation.positionValue} / {positioning.Azimuth.positionValue}

您是否需要至少提供其中一个:

let positionStatus = data.map((positioning) => {
  return (
    <div
      className="temporary"
      key={positioning.key}
    >
      {positioning.Elevation ? positioning.Elevation.positionValue : 0} :
      {positioning.Azimuth ? positioning.Azimuth.positionValue : 0}
    </div>
  )
})

let positionStatus = data.map((positioning) => {
  return (
    <div
      className="temporary"
      key={positioning.key}
    >
      {positioning.Elevation
        ? positioning.Elevation.positionValue
        : positioning.Azimuth.positionValue
      }
    </div>
  )
})