DrSnipesMcGee21
DrSnipesMcGee21

Reputation: 169

Can anyone assist with a Type Error issue while using .map() in React?

Would anyone be able to help me with this error? I am trying to create a drop down picker for country names, pulling from the following API path: https://api.covid19api.com/countries

TypeError: Country.map is not a function
at fetchCountries (index.js:29)
at async fetchAPI (CountryPicker.jsx:13)

Here are the two code sections I am working in:

CountryPicker.jsx

import React, { useState, useEffect } from 'react';
import { NativeSelect, FormControl } from '@material-ui/core';

import styles from './CountryPicker.module.css';

import { fetchCountries } from '../../api';

const CountryPicker = () => {
  const [fetchedCountries, setFetchedCountries] = useState([]);

  useEffect(() => {
    const fetchAPI = async () => {
      setFetchedCountries(await fetchCountries());
    };

    fetchAPI();
  }, [setFetchedCountries]);
  console.log(fetchedCountries);


  return (
    <FormControl className={styles.formControl}>
      <NativeSelect >
        <option value="">Global</option>
      </NativeSelect>
    </FormControl>
  );
};

export default CountryPicker;

index.js

import axios from 'axios';

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

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



        return {  NewConfirmed, TotalConfirmed, NewDeaths, TotalDeaths, NewRecovered, TotalRecovered, Date };

    } catch (error) {
        console.log(error);

    }
}

//TODO
//Fetch Daily Data for charts using axios

export const fetchCountries = async () => {
    try {
      const { data: [ {Country} ] } = await axios.get(countriesURL);



     return Country.map((Country) => Country);
    } catch (error) {
      console.log(error);

    }
  };

I tried to look up why the error may be happening and I found that .map() will not work on a variable that is not an array, but I'm unsure with the current implementation, how to fix this

The data from the API looks like this:

[
    {"Country":"Micronesia, Federated States of","Slug":"micronesia","ISO2":"FM"},
    {"Country":"Bangladesh","Slug":"bangladesh","ISO2":"BD"},
    {"Country":"Bouvet Island","Slug":"bouvet-island","ISO2":"BV"},
    // ...and so on...
]

Upvotes: 0

Views: 82

Answers (2)

xdeepakv
xdeepakv

Reputation: 8125

The restructure is not properly handled here.

const { data: [ x ] } = {data: [{"Country":"Micronesia, Federated States of","Slug":"micronesia","ISO2":"FM"},{"Country":"Bangladesh","Slug":"bangladesh","ISO2":"BD"}]}

Here x will be {"Country":"Micronesia, Federated States of","Slug":"micronesia","ISO2":"FM"}

Next:

const {Country} = x

Here Country will be "Micronesia, Federated States of"

and "Micronesia, Federated States of" is a string and it does not have map function.

So{ data: [ {Country} ] } is wrong way to access all keys.

const fetchCountries = async () => {
  try {
    const countries = await axios
      .get(countriesURL)
      .then((x) => x.data);
    return countries.map(({ Country }) => Country);
  } catch (error) {
    console.log(error);
    return []
  }
};

const fetchCountries = async () => {
  try {
    const countries = await axios
      .get("https://api.covid19api.com/countries")
      .then((x) => x.data);
    return countries.map(({ Country }) => Country).sort();
  } catch (error) {
    console.log(error);
    return []
  }
};
fetchCountries().then(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>

Fetch other info:

// const axios = require("axios"); // for node js

const fetchCountriesInfoParallel = async (countries = []) => {
  const promises = countries.map((country) =>
    axios
      .get(`https://api.covid19api.com/live/country/${country}`)
      .then(({ data }) => data)
  );
  try {
    return await Promise.all(promises);
  } catch (error) {
    console.log(error);
    return [];
  }
};
fetchCountriesInfoParallel(["Afghanistan", "Albania", "Algeria"]).then(
  console.log
);

const fetchCountriesInfoSeries = async (countries = []) => {
  let results = [];
  for (let index = 0; index < countries.length; index++) {
    const country = countries[index];
    const data = await axios
      .get(`https://api.covid19api.com/live/country/${country}`)
      .then(({ data }) => data);
    results.push(data);
  }
  return results;
};
fetchCountriesInfoSeries(["Afghanistan", "Albania", "Algeria"]).then(
  console.log
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1074168

Looking at the result of calling the API, it's in this form:

[
    {"Country":"Micronesia, Federated States of","Slug":"micronesia","ISO2":"FM"},
    {"Country":"Bangladesh","Slug":"bangladesh","ISO2":"BD"},
    {"Country":"Bouvet Island","Slug":"bouvet-island","ISO2":"BV"},
    // ...and so on...
]

So Country isn't an array, it's a property of each object in the array.

If your goal is to extract the Country property from each object, take the array and then use map extracting that property, perhaps with destructuring:

const data = await axios.get(countriesURL);
return data.map(({Country}) => Country);

Upvotes: 3

Related Questions