Search code examples
node.jsreactjstypescripttypeerrorweb-frontend

response.map is not a function - type error?


I'm trying to get a list of countries from an API and this is how I'm doing it.

useEffect(() => {
    const getCountriesList = async () => {
      const response: CovidInfo[] = await getCountries();

      console.log(response.length)

      let countryList = response.map((country: CovidInfo) => ({
        name: country.name,
        iso2: country.iso2,
        iso3: country.iso3,
      }));

      countryList.unshift({name: "Global", iso2: "Global", iso3: "Global"});

      setCountries(countryList);
      setCountry("Global");
    };

    getCountriesList();
  }, []);

My code compiles and builds but at runtime it tells me that response.map is not a function and when I try to log the length of the list it returns undefined. I can't seem to figure out why the response variable is not being recognised as a list. Below, I have also added what CovidInfo and getCountries looks like

export interface CovidInfo {
    name: string;
    iso2: string;
    iso3: string;
    confirmed: {value: number; detail: string;};
    recovered: {value: number; detail: string;};
    deaths: {value: number; detail: string;};
};

const getCountries = async () => {
    try {
        const response = await fetch("https://covid19.mathdro.id/api/countries");
        const data = await response.json();
        return data;
    } catch (error) {
        console.log(error);
        return [];
    }
};

Solution

  • Check the API: https://covid19.mathdro.id/api/countries

    I can see the response format is:

    {
        countries: [
           { name: 'Afghanistan', iso2: 'AF', iso3: 'AFG' },
           ...,
        ]
    }
    

    So when your getCountries returns response.json() it's returning an object, not an array. That is why length is undefined and map is not a function.

    The list of countries you want is inside the property countries.

    For it to work you can change your code to something like:

        console.log(response.countries.length)
    
        let countryList = response.countries.map((country: CovidInfo) => ({
          name: country.name,
          iso2: country.iso2,
          iso3: country.iso3,
        }));