DrSnipesMcGee21
DrSnipesMcGee21

Reputation: 169

Issue with displaying props in Card Component - React

I am building a tracker application in React using an open source API. I am using Axios for HTTP requests. When I pass the objects retrieved from the GET function in index.js, I get an error that reads:

TypeError: Cannot read property 'NewConfirmed' of undefined

Does anyone know why this may be happening based on the code below and why the parameters are coming back undefined? I tried to change my de-structuring of the parameters to reflect the way the API structures it, but it did not work.

index.js

import axios from 'axios';

const url = 'https://api.covid19api.com/summary';

export const fetchData = async () => {
    try {
        const { data: { Global: { NewConfirmed, TotalConfirmed, NewDeaths, TotalDeaths, NewRecovered, TotalRecovered, } } } = await axios.get(url);


        return { NewConfirmed, TotalConfirmed, NewDeaths, TotalDeaths, NewRecovered, TotalRecovered,  } ;
    } catch (error) {
        console.log(error);

    }
}

App.js

import React from 'react';

import {Cards, Chart, CountryPicker} from './components';
import styles from './App.module.css';
import {fetchData} from './api';

class App extends React.Component {

    state ={
        data: {},
    }

    async componentDidMount() {
        const fetchedData = await fetchData();

        this.setState({data: fetchedData});

    }

    render() {

        const { data } = this.state;
        return(
            <div className={styles.container}>
                <Cards data = {data} />
                <CountryPicker />
                <Chart />
            </div>
        );
    }
}

export default App;

Cards.jsx

import React from 'react';
import {Card, CardContent, Typography, Grid} from '@material-ui/core';
import styles from './Cards.module.css';

const Cards = ({data: { Global: { NewConfirmed, TotalConfirmed, NewDeaths, TotalDeaths, NewRecovered, TotalRecovered } } }) => {    


    return(
        <div className = {styles.container}>
            <Grid container spacing={3} justify="center">
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>New Confirmed</Typography>
                        <Typography variant="h5">{NewConfirmed.value}</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of active cases of COVID-19.</Typography>
                    </CardContent>
                </Grid>
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>Total Confirmed</Typography>
                        <Typography variant="h5">{TotalConfirmed.value}</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of active cases of COVID-19.</Typography>
                    </CardContent>
                </Grid>
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>New Deaths</Typography>
                        <Typography variant="h5">{NewDeaths.value}</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of active cases of COVID-19.</Typography>
                    </CardContent>
                </Grid>
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>Total Deaths</Typography>
                        <Typography variant="h5">REAL DATA</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of recoveries of COVID-19.</Typography>
                    </CardContent>
                </Grid>
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>New Recovered</Typography>
                        <Typography variant="h5">REAL DATA</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of deaths of COVID-19.</Typography>
                    </CardContent>
                </Grid>
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>Total Recovered</Typography>
                        <Typography variant="h5">REAL DATA</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of deaths of COVID-19.</Typography>
                    </CardContent>
                </Grid>
            </Grid>
        </div>
    )

}

export default Cards;

Upvotes: 0

Views: 230

Answers (2)

HermitCrab
HermitCrab

Reputation: 3274

in fetchData your reading a Global object but you're returning just the content of the Global object not Global itself. Then in Cards you're receiving props as Global again, but it's just the Global content.

You have:

const Cards = ({data: { Global: { NewConfirmed, TotalConfirmed, NewDeaths, TotalDeaths...

But it should be:

const Cards = ({data: { NewConfirmed, TotalConfirmed, NewDeaths, TotalDeaths...

Upvotes: 1

Mukund Goel
Mukund Goel

Reputation: 599

You are fetching API results after the compountDidMount (i.e. when the render method is called). So your component is rendering without any data and NewConfirmed is undefined since your API call didn't finish yet.

Try adding a check before rendering the component.

import React from 'react';
import {Card, CardContent, Typography, Grid} from '@material-ui/core';
import styles from './Cards.module.css';

const Cards = ({data: { Global: { NewConfirmed, TotalConfirmed, NewDeaths, TotalDeaths, NewRecovered, TotalRecovered } } }) => {    

  if (!NewConfirmed) return null;

    return(
        <div className = {styles.container}>
            <Grid container spacing={3} justify="center">
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>New Confirmed</Typography>
                        <Typography variant="h5">{NewConfirmed.value}</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of active cases of COVID-19.</Typography>
                    </CardContent>
                </Grid>
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>Total Confirmed</Typography>
                        <Typography variant="h5">{TotalConfirmed.value}</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of active cases of COVID-19.</Typography>
                    </CardContent>
                </Grid>
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>New Deaths</Typography>
                        <Typography variant="h5">{NewDeaths.value}</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of active cases of COVID-19.</Typography>
                    </CardContent>
                </Grid>
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>Total Deaths</Typography>
                        <Typography variant="h5">REAL DATA</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of recoveries of COVID-19.</Typography>
                    </CardContent>
                </Grid>
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>New Recovered</Typography>
                        <Typography variant="h5">REAL DATA</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of deaths of COVID-19.</Typography>
                    </CardContent>
                </Grid>
                <Grid item component={Card}>
                    <CardContent>
                        <Typography color="textSecondary" gutterBottom>Total Recovered</Typography>
                        <Typography variant="h5">REAL DATA</Typography>
                        <Typography color="textSecondary">REAL DATE</Typography>
                        <Typography variant="body2">Number of deaths of COVID-19.</Typography>
                    </CardContent>
                </Grid>
            </Grid>
        </div>
    )

}

export default Cards;

Upvotes: 1

Related Questions