2

I am using an API which returns JSON of various different key-value pairs. I am trying to display them inside of render() as a table of 2 columns, key and value, with object keys and values in them, respectively.

  1. The API in fetchBasicDetails() is POST which takes default this.state values as input and returns the JSON output.
  2. The JSON Output object is then stored to birth_details property of this.state using setState method.
  3. Then, I tried to show the object data in <table> tags using forEach and Object.keys, which shows nothing at all.

Any help is appreciated. Thank you.

export default class HoroscopeReport extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      day: 11,
      month: 2,
      year: 2019,
      hours: 12,
      minutes: 59,
      tzone: 5.5,
      lat: 19.22,
      lon: 25.2,
      birth_details:{}
    };
  }

  handleSubmit = event => {
    event.preventDefault();
    //console.log("Received user submitted data"+JSON.stringify(this.state))
    this.fetchBasicDetails();
  };

  fetchBasicDetails() {
        let myHeaders = new Headers();
        myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
        myHeaders.append("Authorization", "Basic XXXXXXXXXXXXXXX");

        let urlencoded = new URLSearchParams();
        urlencoded.append("day", this.state.day);
        urlencoded.append("month", this.state.month);
        urlencoded.append("year", this.state.year);
        urlencoded.append("hour", this.state.hours);
        urlencoded.append("min", this.state.minutes);
        urlencoded.append("lat", this.state.lat);
        urlencoded.append("lon", this.state.lon);
        urlencoded.append("tzone", this.state.tzone);

        let requestOptions = {
          method: 'POST',
          headers: myHeaders,
          body: urlencoded,
          redirect: 'follow'
        };

        fetch("https://json.astrologyapi.com/v1/birth_details", requestOptions)
          .then(response => response.text())
          .then(result => {
            this.setState({ birth_details: result });
          })
          .catch(error => console.log('error', error));
       }

  render() {

    return (
      <div>
{/* FORM SUBMITTION CODE HERE */}
              <h2>Output:-</h2>
              <table border={2} cellPadding={5}>
                <thead>
                  <tr>
                    <td>Key</td>
                    <td>Value</td>
                  </tr>
                </thead>
                <tbody>
                  Object.keys(this.birth_details).forEach(function (element) {
                  return <tr><td>element</td><td>this.birth_details[element]</td></tr>;
                  });
                </tbody>
              </table>
      </div>
    );
  }
}

For reference, This is the output of JSON:-

{"year":2019,"month":2,"day":11,"hour":12,"minute":59,"latitude":19.22,"longitude":25.2,"timezone":5.5,"gender":" ","name":" ","seconds":0,"ayanamsha":24.124044280610406,"sunrise":"10:19:50","sunset":"21:47:13"}

2 Answers 2

5

Usually rendering elements based on an array in React is handled with map() instead of forEach(). The reason is with map() you can manipulate each elements meanwhile iteration and return a completely fit JSX syntax for render method. In the same time forEach() does not return anything, only undefined.

I guess you can try the following:

render() {
    return (
      <div>
        <h2>Output:-</h2>
        <table border={2} cellPadding={5}>
           <thead>
              <tr>
                <td>Key</td>
                <td>Value</td>
              </tr>
           </thead>
           <tbody>
              {
                  this.state.birth_details && 
                  Object.keys(this.state.birth_details).map(function (element) {
                     return <tr>
                       <td>{element}</td>
                       <td>{this.state.birth_details[element]}</td>
                     </tr>;
                  });
              }
           </tbody>
        </table>
      </div>
    );
}

I hope that helps!

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

2 Comments

Oops, I didn't notice you posted an answer! Downsides of posting on mobile, I guess :o)
@cubrr No issues, that happens. :)
0

Remember that you need to use curly braces in JSX to indicate that you want to render the value, not the code as text as-is.

You'll also want to use map instead of forEach. map is used for transforming an array to something else (we're taking a list of strings and mapping them into React elements), whereas forEach is used to just do something with each element and not return anything.

Additionally, you probably meant this.state.birth_details instead of this.birth_details>

<tbody>
{
  Object.keys(this.state.birth_details).map(function (element) {
    return (
      <tr key={element}>
        <td>{element}</td>
        <td>{this.state.birth_details[element]}</td>
      </tr>
    );
  })
}
</tbody>

I've also set the key on the returned element. Read more about lists and keys in React here.

3 Comments

While this definitely helps to print the object data, it is however printing it character-wise! That is, the output in key value columns is like 0 {, 1 ", 2 y, 3 e, 4 a, 5 r
@VaibhavDwivedi In your code where you make the fetch, change response => response.text() to response => response.json().
This parses the JSON for you, since currently you're just taking the JSON as a string and not an object.

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.