1

I would like to display data fetched from an api, by using lifecycle methods. I manage to fetch the data (object) and to populate my data in the state (array). But I can't display the values in the return part.

The first part of the code that seems to work, for readability I removed the error/loading part :

class App extends Component {
    constructor(props) {
        super(props);
    
        this.state = {
          data: [], //putting data in the state
        };
      }
    
    async componentDidMount() {
        fetch("https://covid19.mathdro.id/api")
        .then((response) => response.json())
        .then(
            (data) => {
                this.setState({
                confirmed: data.confirmed, //populate data in this.state
                recovered: data.recovered,
                deaths: data.deaths,
            });
            }
          );
      }
    
    render() {
        const { confirmed, recovered, deaths } = this.state;
        console.log(confirmed, recovered, deaths);
        ...
    }
    
    export default App;

Here is the first return I tried :

return ( <div> {(confirmed, recovered, deaths)} </div>);

I got the

Error: Objects are not valid as a React child (found: object with keys {value, detail}). If you meant to render a collection of children, use an array instead.

Console.log does indeed return objects :

Object { value: 42280709, detail: "https://covid19.mathdro.id/api/confirmed" } Object { value: 28591681, detail: "https://covid19.mathdro.id/api/recovered" } Object { value: 1145557, detail: "https://covid19.mathdro.id/api/deaths" }

By the way, console.log(confirmed.value) doesn't return anything, why?

So I decided to use the Array.prototype.map() :

return (
    <div> 
        {this.state.confirmed.map(i => (<div>{i.value}</div>))} 
    </div>);

And now I got the

TypeError: confirmed is undefined

I don't understand this error, how can console.log(confirmed) return something if it is undefined?

Other paths I explored : using JSON.parse, putting key in the map, removing the {}, ..

I went through several stackoverflow questions, but still don't understand what to change : React render: Objects are not valid as a React child Objects are not valid as a React child. If you meant to render a collection of children, use an array instead

Any clues? Thanks !

Dharman
  • 30,962
  • 25
  • 85
  • 135
Mamily
  • 45
  • 6
  • I've rolled back your edit adding an answer in your question. I'm glad you found a solution to your problem. However, an actual answer/solution should **not** be edited into your Question. In general, you should [edit] the Question to *clarify the Question*, but not to include an Answer within the Question. You should create your own Answer with the code you used to solve your problem, then accept it (the system may require a 48-hour delay prior to accepting your own answer). – Dharman Oct 24 '20 at 22:33

2 Answers2

1

I have checked the API that you've been using, I see confirmed, recovered, deaths are objects not arrays(That's why you're getting those error). you should do the following code.

class App extends Component {
    constructor(props) {
        super(props);
        this.state = { confirmed: {}, recovered: {}, deaths: {} };
      }
    
    async componentDidMount() {
      fetch("https://covid19.mathdro.id/api")
      .then((response) => response.json())
      .then(
          (data) => {
            const { confirmed, recovered, deaths } = data
            this.setState({ confirmed, recovered, deaths });
          }
        );
      }
    
    render() {
        const { confirmed, recovered, deaths } = this.state;
        return (
          <div>
            <div>Confirmed: { confirmed.value || 0}</div>
            <div>Recovered: { recovered.value || 0}</div>
            <div>Deaths: { deaths.value || 0 }</div>
          </div>
        )
    }
}
    
export default App;
Naren
  • 4,152
  • 3
  • 17
  • 28
0

First of all you cannot render objects inside JSX, it should be a valid JSX element, look into the ReactNode type definitions for more information.

Second issue you are facing is due to your initial state, which is an object with an empty array called data; this.state = { data: [] };. So when you try to access the confirmed property of the this.state.data; it fails because your data has not come through from the api call yet.

What you have to do is before rendering anything to check if this.state.data has a property called confirmed

 return (<div>
          {this.state.confirmed && <div> 
            {this.state.confirmed.map(i => (<div>{i.value}</div>))} 
         </div>}
        </div>)
Anuja
  • 908
  • 6
  • 11