1

I am working on mapping JSON to Data driven rendering within react. To accomplish some of the things I need to do. I am going to require Nested JSON. When attempting to map this data, I keep running into values that I cannot map. Specifically when trying (mapObject.object.value) where I am attempting to pass the nested values into an interpolated div.

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;

The relevant JSON has been provided for context of the issue, but is being served from JSON.server for sake of development speed. It seems that the issue is that I am receiving Object {key: 0, Elevation: Object } Object { key: 1, Azimuth: Object } where I cannot go down a level into the object itself by calling {positioning.Elevation.positionValue}. My question is, how would I go about mapping this so that I can get those interior object values tied to Elevation, and Azimuth?

12
  • Have you tried mapping through data.PositionComponent.map(...) instead of data? Commented Nov 14, 2017 at 20:29
  • @mersocarlin I have not, but I am trying now. Commented Nov 14, 2017 at 20:31
  • @mersocarlin It throws a data.PositionComponent is undefined error Commented Nov 14, 2017 at 20:34
  • What is the output if you console.log(data) before mapping? Commented Nov 14, 2017 at 20:43
  • In your data, positioning.Elevation may or may not be defined. If you only ever have Elevation or Azimuth, then you can do: {(positioning.Elevation) ? positioning.Elevation.positionValue : positioning.Azimuth.positionValue} Commented Nov 14, 2017 at 20:44

2 Answers 2

2

The main issue here is that you got different keys on each object that holds the nested key you want to grab.
You may try to access it conditionally and check the existing of Elevation OR Azimuth and access respectively.
The downside for this approach that when you add a new key, another condition should be added. So you may want a more generic approach.

You can use Object.entries and .map through the keys and return the for each positionValue. if a certain key doesnt hold it then undefined will be evaluated which map will ignore and wont return it.
Something like this:

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

I would take out the rendering logic out to another method and wont store a markup in state.
Another thing you will want to change is to avoid the use of fetching or side effects in componentWillMount

Here is a running example of your code (i didn't use fetch as i don't have your data in a server)

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>

Sign up to request clarification or add additional context in comments.

3 Comments

Assuming I wanted to do this inside a fetch command, would I follow the same structure, and replace renderPositionStatus with the fetch?
you could technically but i advice against that. in my opinion a fetch callback responsibility is... well, to fetch the data. i would store the fetched data in the state, this will trigger another render call this time the state is not empty and the function renderPositionstatus for example will return the markup you want with the new data. fetch should only fetch data and trigger an action inside a callback in my opinion.
Thank you very much. I appreciate the advisement.
0

Thought it might be a JSON error, but you are trying to access an undefined prop within your object.

This is your data:

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

Not all elements have Elevation nor Azimuth props. First one has only Elevation whereas second one has Azimuth.

Therefore, this line will always break:

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

Should you need to provide at least one of them:

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>
  )
})

or

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

1 Comment

Apologies, and to clarify that is not meant to represent a division of two numbers. It is meant to signify a division of strings where the "/" is sitting

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.