0

I'm pulling data from an API using a simple fetch call. The API call pulls an object and I'm using JSON.Stringify to extract the data in readable format, however, I just want the number that it produces. Here is an excerpt from the API

{
  "confirmed": {
    "value": 24637475,
    "detail": "https://covid19.mathdro.id/api/confirmed"
  },
  "recovered": {
    "value": 16108272,
    "detail": "https://covid19.mathdro.id/api/recovered"
  },

I'm just trying to get the confirmed.value

here is my current code

import React, { useState, useEffect } from "react";

const Cards = () => {
    const [hasError, setErrors] = useState(false);
    const [data, setData] = useState({});

    async function fetchData() {
        const res = await fetch("https://covid19.mathdro.id/api");
        res
            .json()
            .then(res => setData(res))
            .catch(err => setErrors(err));
    }

    useEffect(() => {
        fetchData();
    }, []);

    return (
        <div>
            <span>{JSON.stringify(data.confirmed)}</span>
            <hr />
            <span>Has error: {JSON.stringify(hasError)}</span>
        </div>
    );
};
export default Cards;
4156
  • 380
  • 4
  • 17
  • Doesn't `data.confirmed && data.confirmed.value` give you what you need? – charlietfl Aug 29 '20 at 03:58
  • @keikai A string can't have a property `confirmed` – charlietfl Aug 29 '20 at 03:59
  • @charlietfl both of those give me undefined – 4156 Aug 29 '20 at 04:00
  • right...on first render, but what about after data is loaded? – charlietfl Aug 29 '20 at 04:01
  • @charlietfl ```"value":24649431,"detail":"https://covid19.mathdro.id/api/confirmed"}``` – 4156 Aug 29 '20 at 04:02
  • Ok...that's the stringified output, so wrap what's in my first comment in `{}` and try that. No stringify needed. You have to account for data not arriving until after first render occurs – charlietfl Aug 29 '20 at 04:04
  • @charlietfl still gives me that 'value' is undefined. using both ```data.confirmed``` as well as ```data.confirmed.value``` – 4156 Aug 29 '20 at 04:07
  • And that is when you don't use stringify? – charlietfl Aug 29 '20 at 04:11
  • @charlietfl correct. I've never done this without using a ton of hooks to accomplish it. But all I wanted to do was show the value inside 'confirmed' but to answer your question I use ```{data.confirmed.value}``` – 4156 Aug 29 '20 at 04:13
  • Ok...and that will definitely be undefined first render since default object doesn't have the nested properties. Won't be defined until after the fetch completes and updates state – charlietfl Aug 29 '20 at 04:15
  • @charlietfl any ideas on how to fix it? – 4156 Aug 29 '20 at 04:22
  • 1
    Not really . Not making sense you can get the stringified version to show but not the object version. Create a demo that reproduces it – charlietfl Aug 29 '20 at 04:24
  • @charlietfl I actually ended up scapping it and just rewriting it after a good sip of coffee and I got it working, answer is above. – 4156 Aug 29 '20 at 04:35
  • 1
    Yeah, if that's all you ever use from the request, much cleaner – charlietfl Aug 29 '20 at 04:39
  • @charlietfl what if I wanted to put the API call in another folder and call it in different places? Just to make the code look simpler? – 4156 Aug 29 '20 at 04:41
  • You mean like import a function that returns the request promise? – charlietfl Aug 29 '20 at 04:43
  • @charlietfl yes, just sticking the API call in another folder and calling it with a useEffect. – 4156 Aug 29 '20 at 04:46
  • Do some searching around on how to create custom async hooks. Can build one with useeffect right in it and simply import that custom hook – charlietfl Aug 29 '20 at 04:49

1 Answers1

0

I ended up figuring this out after taking a second to look it over and just refactoring it.


import React, { useState, useEffect } from "react";

const Cards = () => {
    const [confirmed, setConfirmed] = useState("");

    useEffect(() => {
        fetch("https://covid19.mathdro.id/api")
            .then((responseData) => responseData.json())
            .then((data) => {
                setConfirmed(data.confirmed.value)
            })
    })


    return (
        <div>
            {confirmed}
        </div>
    );
};
export default Cards;

I just put everything in the useEffect and that ended up solving my problem. I'm not really sure why that was the solution.

4156
  • 380
  • 4
  • 17
  • Even this is wrong it will run on every render . Better way to check is this `data && {renderComponent}` whatever data component you want to show – Shubham Verma Aug 29 '20 at 05:48