user16788910
user16788910

Reputation:

Can't iterate through an object using map in ReactJS

I'm trying to iterate through an object using map but I get this error both on the site and console:

TypeError: Cannot read property 'map' of undefined

I'm trying to display only the countryName of the city and the population but it seems that map is not working. I'm fetching json from a geoAPI which gives returns this:

{
   "totalResultsCount":12132606,
   "geonames":[
      {
         "adminCode1":"01",
         "lng":"22.78333",
         "geonameId":907155,
         "toponymName":"Mayela",
         "countryId":"895949",
         "fcl":"V",
         "population":0,
         "countryCode":"ZM",
         "name":"Mayela",
         "fclName":"forest,heath,...",
         "adminCodes1":{
            "ISO3166_2":"01"
         },
         "countryName":"Zambia",
         "fcodeName":"forest(s)",
         "adminName1":"Western",
         "lat":"-15.33333",
         "fcode":"FRST"
      },
      {
         "adminCode1":"03",
         "lng":"33.31667",
         "geonameId":907156,
         "toponymName":"Mayekeya",
         "countryId":"895949",
         "fcl":"P",
         "population":0,
         "countryCode":"ZM",
         "name":"Mayekeya",
         "fclName":"city, village,...",
         "adminCodes1":{
            "ISO3166_2":"03"
         },
         "countryName":"Zambia",
         "fcodeName":"populated place",
         "adminName1":"Eastern",
         "lat":"-12.36667",
         "fcode":"PPL"
      },
      {
         "adminCode1":"01",
         "lng":"23.15",
         "geonameId":907157,
         "toponymName":"Mayekabu",
         "countryId":"895949",
         "fcl":"P",
         "population":0,
         "countryCode":"ZM",
         "name":"Mayekabu",
         "fclName":"city, village,...",
         "adminCodes1":{
            "ISO3166_2":"01"
         },
         "countryName":"Zambia",
         "fcodeName":"populated place",
         "adminName1":"Western",
         "lat":"-15.6",
         "fcode":"PPL"
      },
      {
         "adminCode1":"05",
         "lng":"30.45064",
         "geonameId":907158,
         "toponymName":"Mayebwe",
         "countryId":"895949",
         "fcl":"H",
         "population":0,
         "countryCode":"ZM",
         "name":"Mayebwe",
         "fclName":"stream, lake, ...",
         "adminCodes1":{
            "ISO3166_2":"05"
         },
         "countryName":"Zambia",
         "fcodeName":"stream",
         "adminName1":"Northern",
         "lat":"-10.32684",
         "fcode":"STM"
      },
      {
         "adminCode1":"01",
         "lng":"22.96667",
         "geonameId":907159,
         "toponymName":"Mayayu",
         "countryId":"895949",
         "fcl":"H",
         "population":0,
         "countryCode":"ZM",
         "name":"Mayayu",
         "fclName":"stream, lake, ...",
         "adminCodes1":{
            "ISO3166_2":"01"
         },
         "countryName":"Zambia",
         "fcodeName":"waterhole(s)",
         "adminName1":"Western",
         "lat":"-15",
         "fcode":"WTRH"
      },
      {
         "adminCode1":"10",
         "lng":"33.23333",
         "geonameId":907160,
         "toponymName":"Mayaya",
         "countryId":"895949",
         "fcl":"H",
         "population":0,
         "countryCode":"ZM",
         "name":"Mayaya",
         "fclName":"stream, lake, ...",
         "adminCodes1":{
            "ISO3166_2":"10"
         },
         "countryName":"Zambia",
         "fcodeName":"stream",
         "adminName1":"Muchinga",
         "lat":"-10",
         "fcode":"STM"
      },
      {
         "adminCode1":"02",
         "lng":"28.28333",
         "geonameId":907161,
         "toponymName":"Mayaya",
         "countryId":"895949",
         "fcl":"P",
         "population":0,
         "countryCode":"ZM",
         "name":"Mayaya",
         "fclName":"city, village,...",
         "adminCodes1":{
            "ISO3166_2":"02"
         },
         "countryName":"Zambia",
         "fcodeName":"populated place",
         "adminName1":"Central",
         "lat":"-14.15",
         "fcode":"PPL"
      },
      {
         "adminCode1":"03",
         "lng":"30.25968",
         "geonameId":907162,
         "toponymName":"Mayawa",
         "countryId":"895949",
         "fcl":"P",
         "population":0,
         "countryCode":"ZM",
         "name":"Mayawa",
         "fclName":"city, village,...",
         "adminCodes1":{
            "ISO3166_2":"03"
         },
         "countryName":"Zambia",
         "fcodeName":"populated place",
         "adminName1":"Eastern",
         "lat":"-14.40278",
         "fcode":"PPL"
      },
      {
         "adminCode1":"06",
         "lng":"24.25763",
         "geonameId":907163,
         "toponymName":"Mayau",
         "countryId":"895949",
         "fcl":"H",
         "population":0,
         "countryCode":"ZM",
         "name":"Mayau",
         "fclName":"stream, lake, ...",
         "adminCodes1":{
            "ISO3166_2":"06"
         },
         "countryName":"Zambia",
         "fcodeName":"stream",
         "adminName1":"North-Western",
         "lat":"-12.75585",
         "fcode":"STM"
      },
      {
         "adminCode1":"01",
         "lng":"22.96667",
         "geonameId":907164,
         "toponymName":"Mayapi",
         "countryId":"895949",
         "fcl":"P",
         "population":0,
         "countryCode":"ZM",
         "name":"Mayapi",
         "fclName":"city, village,...",
         "adminCodes1":{
            "ISO3166_2":"01"
         },
         "countryName":"Zambia",
         "fcodeName":"populated place",
         "adminName1":"Western",
         "lat":"-14.96667",
         "fcode":"PPL"
      }
    
   ]
}

I tried to google around and tried some map solutions but I feel that the problem is that I don't handle reading an object correctly. And here is my code:

import react, { useState, useEffect } from "react";
import TextFieldAPI from "./TextFieldAPI";
import ButtonAPI from "./ButtonAPI";
import Card from "@material-ui/core/Card";
import Button from "@material-ui/core/Button";
import SearchIcon from "@material-ui/icons/Search";

const url = "http://api.geonames.org/searchJSON?username=weknowit";

function FetchGeoAPI() {
  const [data, setData] = useState();

  const getData = () => {
    fetch(url)
      .then((response) => response.json())
      .then((json) => {
        console.log(json);
        setData(json);
      });
  };

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


  return (
    <div>
      {data.map((geo) => {
        return (
          <div>
            <h5>{geo.geonames.name}</h5>
            <h5>{geo.geonames.population}</h5>
          </div>
        );
      })}
    </div>
  );
}
export default FetchGeoAPI;

Upvotes: 1

Views: 92

Answers (6)

Andy
Andy

Reputation: 63524

I probably wouldn't use optional chaining here as sometimes you want to let the user know that data is being retrieved, and chaining makes it a little more difficult.

Here's an example that checks for the existence of the data but returns a "Loading" message if the data hasn't been returned and the state updated.

const { useEffect, useState } = React;

const geonames={totalResultsCount:12132606,geonames:[{adminCode1:"01",lng:"22.78333",geonameId:907155,toponymName:"Mayela",countryId:"895949",fcl:"V",population:0,countryCode:"ZM",name:"Mayela",fclName:"forest,heath,...",adminCodes1:{ISO3166_2:"01"},countryName:"Zambia",fcodeName:"forest(s)",adminName1:"Western",lat:"-15.33333",fcode:"FRST"},{adminCode1:"03",lng:"33.31667",geonameId:907156,toponymName:"Mayekeya",countryId:"895949",fcl:"P",population:0,countryCode:"ZM",name:"Mayekeya",fclName:"city, village,...",adminCodes1:{ISO3166_2:"03"},countryName:"Zambia",fcodeName:"populated place",adminName1:"Eastern",lat:"-12.36667",fcode:"PPL"},{adminCode1:"01",lng:"23.15",geonameId:907157,toponymName:"Mayekabu",countryId:"895949",fcl:"P",population:0,countryCode:"ZM",name:"Mayekabu",fclName:"city, village,...",adminCodes1:{ISO3166_2:"01"},countryName:"Zambia",fcodeName:"populated place",adminName1:"Western",lat:"-15.6",fcode:"PPL"},{adminCode1:"05",lng:"30.45064",geonameId:907158,toponymName:"Mayebwe",countryId:"895949",fcl:"H",population:0,countryCode:"ZM",name:"Mayebwe",fclName:"stream, lake, ...",adminCodes1:{ISO3166_2:"05"},countryName:"Zambia",fcodeName:"stream",adminName1:"Northern",lat:"-10.32684",fcode:"STM"},{adminCode1:"01",lng:"22.96667",geonameId:907159,toponymName:"Mayayu",countryId:"895949",fcl:"H",population:0,countryCode:"ZM",name:"Mayayu",fclName:"stream, lake, ...",adminCodes1:{ISO3166_2:"01"},countryName:"Zambia",fcodeName:"waterhole(s)",adminName1:"Western",lat:"-15",fcode:"WTRH"},{adminCode1:"10",lng:"33.23333",geonameId:907160,toponymName:"Mayaya",countryId:"895949",fcl:"H",population:0,countryCode:"ZM",name:"Mayaya",fclName:"stream, lake, ...",adminCodes1:{ISO3166_2:"10"},countryName:"Zambia",fcodeName:"stream",adminName1:"Muchinga",lat:"-10",fcode:"STM"},{adminCode1:"02",lng:"28.28333",geonameId:907161,toponymName:"Mayaya",countryId:"895949",fcl:"P",population:0,countryCode:"ZM",name:"Mayaya",fclName:"city, village,...",adminCodes1:{ISO3166_2:"02"},countryName:"Zambia",fcodeName:"populated place",adminName1:"Central",lat:"-14.15",fcode:"PPL"},{adminCode1:"03",lng:"30.25968",geonameId:907162,toponymName:"Mayawa",countryId:"895949",fcl:"P",population:0,countryCode:"ZM",name:"Mayawa",fclName:"city, village,...",adminCodes1:{ISO3166_2:"03"},countryName:"Zambia",fcodeName:"populated place",adminName1:"Eastern",lat:"-14.40278",fcode:"PPL"},{adminCode1:"06",lng:"24.25763",geonameId:907163,toponymName:"Mayau",countryId:"895949",fcl:"H",population:0,countryCode:"ZM",name:"Mayau",fclName:"stream, lake, ...",adminCodes1:{ISO3166_2:"06"},countryName:"Zambia",fcodeName:"stream",adminName1:"North-Western",lat:"-12.75585",fcode:"STM"},{adminCode1:"01",lng:"22.96667",geonameId:907164,toponymName:"Mayapi",countryId:"895949",fcl:"P",population:0,countryCode:"ZM",name:"Mayapi",fclName:"city, village,...",adminCodes1:{ISO3166_2:"01"},countryName:"Zambia",fcodeName:"populated place",adminName1:"Western",lat:"-14.96667",fcode:"PPL"}]};

function Example() {

  const [ data, setData ] = useState();

  function getData() {
    setTimeout(() => {
      setData(geonames);
    }, 2000);
  }

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

  if (!data) return <div>Loading</div>;

  return (
    <div>
      {data.geonames.map(({ name, population }) => {
        return (
          <div>
            <p>{name}</p>
            <p>{population}</p>
          </div>
        )}
      )}
    </div>
  );
};

// Render it
ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Upvotes: 0

Jacopo Bonomi
Jacopo Bonomi

Reputation: 458

You need to call at bootstrap your fetch function.

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

And add to your map function a ? to check if is not null.

Edit: after see response API.

{data?.geonames?.map((geo) => {
return (
  <div>
    <h5>{geo.name}</h5>
    <h5>{geo.population}</h5>
  </div>
 );
})}

Upvotes: 1

Rishab Vaigankar
Rishab Vaigankar

Reputation: 443

import react, { useState, useEffect } from "react";
import TextFieldAPI from "./TextFieldAPI";
import ButtonAPI from "./ButtonAPI";
import Card from "@material-ui/core/Card";
import Button from "@material-ui/core/Button";
import SearchIcon from "@material-ui/icons/Search";

const url = "http://api.geonames.org/searchJSON?username=weknowit";

function FetchGeoAPI() {
  const [data, setData] = useState();

  const getData = () => {
    fetch(url)
      .then((response) => response.json())
      .then((json) => {
        console.log(json);
        setData(json);
      });
  };
  

  return (
    <div>
      {
        data?.geonames.map((geo) => {
        return (
          <div>
            <h5>{geo.name}</h5>
            <h5>{geo.population}</h5>
          </div>
        );
      })}
    </div>
  );
}
export default FetchGeoAPI;
added the solution I think this should help you

Upvotes: 0

Tushar Shahi
Tushar Shahi

Reputation: 20431

The data you are getting after .json() is still an object. It is the geonames key, which is actually an array.

 {data?.geonames.map(

Upvotes: 0

Muhammad Usama Ashraf
Muhammad Usama Ashraf

Reputation: 564

you cannot run map on object it is available only for arrays

you got object in data and it contains geonames array so use this

enter image description here

<div>
  {data.geonames.map((geo) => {
    return (
      <div>
        <h5>{geo.name}</h5>
        <h5>{geo.population}</h5>
      </div>
    );
  })}
</div>

Upvotes: 0

vaira
vaira

Reputation: 2270

you need to iterate over the array inside the data not the data object.

data.geonames.map(() =>  .... )

Upvotes: 0

Related Questions