Dogukan Aktas
Dogukan Aktas

Reputation: 113

ReactJS: value of the object is undefined

I'm trying to make an application that shows Covid 19 numbers. I want to show global numbers when the component is rendered, so I used useEffect hooks for this. When I try to display global.confirmed it's returns an object but when I try to display global.confirmed.value I get a Cannot read property 'value' of undefined error. How can I fix this?

import React from "react";
import "./App.css";
import axios from "axios";
import { useState, useEffect } from "react";
import "./App.css";

const App = () => {
  const [countries, SetCountries] = useState([]);
  const [cases, SetCases] = useState([]);
  const [global, SetGlobal] = useState({});

  const urlGlobal = "https://covid19.mathdro.id/api/"
  const urlCountries = "https://covid19.mathdro.id/api/countries/";

  useEffect(() => {
    axios.get(urlGlobal).then(res => SetGlobal(res.data))
    axios.get(urlCountries).then((res) => SetCountries(res.data.countries));
  }, []);

  const showCases = (e) => {
    const urlCases = `https://covid19.mathdro.id/api/countries/${e.target.value}`;
    axios.get(urlCases).then((res) => SetCases(res.data));
  };


  return (
    <div>
      <div>
        <p>Infected</p>
        <p>{cases.confirmed.value}</p>
        <p>{cases.lastUpdate}</p>
        <p>Number of active cases of COVID-19</p>
      </div>
      <div>
        <p>Recovered</p>
        <p>{cases.recovered.value}</p>
        <p>{cases.lastUpdate}</p>
        <p>Number of recoveries from COVID-19</p>
      </div>
      <div>
        <p>Deaths</p>
        <p>{cases.deaths.value}</p>
        <p>{cases.lastUpdate}</p>
        <p>Number of deaths caused by COVID-19</p>
      </div>
      <select name="countries" onChange={(e) => showCases(e)}>
        {countries.map((val, i) => (
          <option key={i} value={val.name}>
            {val.name}
          </option>
        ))}
      </select>
    </div>
  );
};

export default App;

global: enter image description here

Upvotes: 3

Views: 2021

Answers (1)

David
David

Reputation: 218818

By default you set cases to an empty array:

const [cases, SetCases] = useState([]);

And on the initial render, while it's still an empty array, you try to access properties which aren't defined on an array:

<p>{cases.confirmed.value}</p>

There are essentially two problems here:

  1. Arrays don't have properties like confirmed. Do you expect cases to be an object instead?
  2. When the component first renders, cases has no data, so don't attempt to display that data.

Let cases start off undefined (since in the usage it looks like it shouldn't even be an array):

const [cases, SetCases] = useState();

And only display it when it's not undefined:

<div>
  <p>Infected</p>
  <p>{cases && cases.confirmed.value}</p>
  <p>{cases && cases.lastUpdate}</p>
  <p>Number of active cases of COVID-19</p>
</div>

You can repeat for other usages, or wrap all of the usages in a single check for cases:

{
  cases &&
  <div>
    <p>Infected</p>
    <p>{cases.confirmed.value}</p>
    <p>{cases.lastUpdate}</p>
    <p>Number of active cases of COVID-19</p>
  </div>
}

The idea is that these elements won't even try to render if cases is "falsey" (which undefined is), so the code won't try to access properties like confirmed until cases exists.


However, if cases should be an array, then what you also have is a logical error in your overall markup structure because arrays don't have properties like confirmed. Perhaps you meant to calculate values from within the array. If that's the case then you can keep the initial state as an empty array:

const [cases, SetCases] = useState([]);

But you'd need to change your markup to something that uses an array. For example, maybe something like:

{
  cases.map(c => (
    <div>
      <p>Infected</p>
      <p>{c.confirmed.value}</p>
      <p>{c.lastUpdate}</p>
      <p>Number of active cases of COVID-19</p>
    </div>
  ))
}

I'm not entirely familiar with the data you're using or how you want it displayed, but a key consideration here is simply the difference between an object and an array of objects. Which you'll need to determine in your code.

Upvotes: 3

Related Questions