Reputation:
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
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
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
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;
Upvotes: 0
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
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
<div>
{data.geonames.map((geo) => {
return (
<div>
<h5>{geo.name}</h5>
<h5>{geo.population}</h5>
</div>
);
})}
</div>
Upvotes: 0
Reputation: 2270
you need to iterate over the array inside the data not the data object.
data.geonames.map(() => .... )
Upvotes: 0