Im trying to access data from an API and render the results. Im storing each object in a separate state and im trying to map through each state, however this throws the following Error.
My code is:
state = {
events: [],
items: [],
isLoading: true
}
// fetchData = () => {
componentDidMount() {
const url = 'http://www.mocky.io/v2/5c8673f0340000981789c0da'
axios.get(url).then(response => {
this.setState({ items: response.data, isLoading: false, events: response.data[0] })
console.log(this.state.events)
})
}
render() {
return(
<div>
<div>
<h1>26/2</h1>
<ul>
{ this.state.events.map(event => (<li>{event.activity}</li>)) }
</ul>
</div>
<div>
<h1>27/2</h1>
<ul>
</ul>
</div>
</div>
)
}
}
API structure:
[
{
"id": 1,
"activity": "lunch",
"startDate": "2019-02-26 12:00",
"endDate": "2019-02-26 13:00",
"location": "Lagerhuset"
},
{
"id": 2,
"activity": "meeting",
"startDate": "2019-02-26 22:00",
"endDate": "2019-02-27 07:00",
"location": "online"
},
{
"id": 3,
"activity": "meeting",
"startDate": "2019-02-26 10:00",
"endDate": "2019-02-26 12:00",
"location": "Lagerhuset"
}
]
Now im wondering if what I'm trying to achieve even is possible? And if so, what am I doing wrong? Thanks.
items contain the array of items. events just contain the first item which is an object. Hence the map fails.
Either use :
{this.state.items.map(event => (
<li>{event.activity}</li>
))}
or this :
<li>{this.state.events.activity}</li>
Related
App.js
I am facing this issue file error - Uncaught TypeError: items.data.map is not a function. I have tried some other options but did not work. I cant seem to find what I am doing wrong.
.then((res) => res.json())
.then((json) => {
this.setState({
items: json,
DataisLoaded: true
});
})
}
render() {
const { DataisLoaded, items } = this.state;
if (!DataisLoaded) return <div>
<h1> Loading data ... </h1> </div> ;
return (
<div className = "App">
<h1> Fetch data from an api in react </h1> {
items.data.map((item) => (
<ol key = { item.data} >
Continents: {item.data[0]}
</ol>
))
}
</div>
);
}
}
export default App;
JSON Data
Nested API data from json data type.
{
"data": {
"data": [
{
"project_id": "xxxx",
"title": "xxx34",
"description": "xxx23",
"expense": 1699126,
"budget": 6418516,
"country": "xxx",
"sector": [
{
"name": "Accelerate structural transformations",
"code": "18"
}
],
"sdg": [
{
"name": "Peace, justice, and strong institutions",
"id": "16"
}
],
"signature_solution": [
{
"name": "Strengthen effective, inclusive and accountable governance",
"id": "2"
}
],
"donor": [
"Australian DFAT",
"GLOBAL FUND TO FIGHT AIDS, TUBERCULOSIS",
"UNITED NATIONS DEVELOPMENT PRO"
],
"marker": [
"Hows",
"Joint Programme",
"Partner",
"Whos",
"COVID-19 Response"
]
},
{
],
"links": {
"next": null,
"previous": null
},
"count": 44
},
"status": 200,
"success": true
}
I tried data.data.map but still facing the same error. What am I doing wrong here?
Firstly, the TypeError you got is syntax error. The implementation of an arrow function must follow by curly brackets
items.data.map((item) => (
<ol key = { item.data} >
Continents: {item.data[0]}
</ol>
))
to
items.data.map((item) => {
<ol key = { item.data} >
Continents: {item.data[0]}
</ol>
})
Secondly, items you are mapping is a nest of JSON object - key: value pair. It's not suitable for mapping.
The mapping iterator or iterating an array is perfect when used to retrieve
data from a sequence item have the same or similar structure.
E.g:
const arr = [{"id": "1", "name": "a"}, {"id": "2", "name": "b"}, {"id": "3", "name": "c"}];
arr.map((item) => {
console.log(item.id);
console.log(item.name);
})
You should pretreat your data first.
i want to display submodule names also inside div
this is my api data
"predefined": [
{
"id": 2,
"mainModule": "bonding",
"description": "some random description 2",
"sub_module": [
{
"id": 3,
"subModuleName": "activity of bonding",
"completed": false
},
{
"id": 4,
"subModuleName": "self care",
"completed": false
}
]
},
{
"id": 1,
"mainModule": "main module 1",
"description": "some random description",
"sub_module": [
{
"id": 1,
"subModuleName": "sub module 1",
"completed": false
},
{
"id": 2,
"subModuleName": "sub module 2",
"completed": false
}
]
}
],
this is my axios to fetch the data from api and set my state called items
axios
.get(
"url",
config
)
.then((res) => {
this.setState({ items: res.data.predefined });
});
}
this is the jsx i have used to display my api here personData.mainmodule and personData.description works fine since submoule names are inside an arrray not rendering i cannot use it as {personData.sub_module[0].subModuleName}
{this.state.items.map((personData) => {
return (
<>
<div className="activity">
<h3>{personData.mainModule}</h3>
<span>{personData.description}</span>
{this.state.item.map((personData) => {
return (
<>
{personData.sub_module.subModuleName} //error
</>
);
})}
</div>
</>
);
})}
You should use current personData variable to access sub_module properties. And then you use another Array.map to render it.
{
personData.sub_module.map(item => {
return (
<>
{item.subModuleName}
</>
);
})
}
{
personData.sub_module.map(item => {
return (
<>
{item.subModuleName}
</>
);
})
}
You don't need to iterate this.state.items again to get sub_module. You can do like this
{this.state.items.map((personData) => {
return (
<>
<div className="activity">
<h3>{personData.mainModule}</h3>
<span>{personData.description}</span>
{personData.sub_module.map((data) => {
return <div>{data.subModuleName}</div>;
})}
</div>
</>
);
})}
This way you can iterate sub_module properly.
I have to map the nested JSON result in React. The below one is the response I got as response from backend API.
{
"id": 2,
"name": "sanjna",
"email": "vv#gmail.com",
"address": "iiiii, hhh",
"gender": "1",
"tagline": "Friendly to all",
"description": "4 years experience in programming",
"languages": "English ",
"key_skills": [
{
"id": 1,
"name": "RUBY ON RAILS, HTML, BOOTSTRAP, JQUERY, REACT",
"relevant_experience": "4"
},
{
"id": 2,
"name": "ruby",
"relevant_experience": "2"
}
],
"certifications": [
{
"id": 1,
"name": "MCA",
"institution_name": "vvv unversity",
"certification_date": "20-12-2020",
"image": null
},
{
"id": 2,
"name": "HTML training",
"institution_name": "nnn unversity",
"certification_date": "20-12-2022",
"image": null
}
],
"educations": [
{
"id": 1,
"qualification": "MCA",
"course": "Masters Degree PG",
"institute": "kkk",
"ins_location": "jjjj",
"passing_year": "2015"
}
]
}
This is my React code to get this response
const [singleUserDetail, setsingleUserDetail] = React.useState('');
let logged_user_id = job_seeker.actable_id;
const getsingleUserDetails = (logged_user_id) => {
axios
.get(`http://localhost:3001/users/${logged_user_id}`, { withCredentials: true })
.then((response) => {
const singleUserDetail = response.data;
setsingleUserDetail(response.data)
console.log(response.data); //prints the above JSON results in console
})
.catch((error) => {
console.log(" error", error);
});
};
React.useEffect(() => {
getsingleUserDetails(logged_user_id);
}, [logged_user_id]);
When I prints {singleUserDetail.name} it gives me result sanjna
{singleUserDetail.email} it gives me result vvv#gmail.com
{singleUserDetail. address} it gives me result iiiii, hhh. from my above JSON result
But how to print keyskills, certifications and educations here with mapping. I'm a beginner in React.
Youu can do something like this, my example is very simple,but you can complicate this as much as you need, with conditions or loops in loops.
<div>
{singleUserDetail.name},{singleUserDetail.email},{singleUserDetail.address},{singleUserDetail.gender},{singleUserDetail.tagline},{singleUserDetail.description}, {singleUserDetail.languages}
</div>
{singleUserDetail.key_skills.map((skill)=>{
return(
<div key={skill.id}>
{skill.name}:{skill.relevant_experience}
</div>
);
})}
{singleUserDetail.certifications.map((certification)=>{
return(
<div key={certification.id}>
{certification.name},{certification.institution_name},{certification.certification_date}
</div>
);
})}
{singleUserDetail.educations.map((education)=>{
return(
<div key={education.id}>
{education.qualification},{education.course},{education.institute}
</div>
);
})}
For more information, React documentation
When I am trying the console log the state its saying Undefined.. I also placed the JSON file.
I have posted the endpoint json file here. I believe there is an issue while hooking up json.
When I am trying the console log the state its saying Undefined.. I also placed the JSON file.
I have posted the endpoint json file here. I believe there is an issue while hooking up json.
class App extends Component {
state = {
content: [{ coord: "" }, { base: "" }]
};
componentDidMount() {
axios
.get(
"https://api.openweathermap.org/data/2.5/weather?q=berlin&appid=240ef553958220e0d857212bc790cd14"
)
.then(res => {
this.setState({
content: [
{
coord: res.data.coord
},
{ base: res.data.base }
]
});
});
}
render() {
console.log(this.state.content.coord);
return (
<div className="App center">
<h2 className="blue-text">Weather App</h2>
<div></div>
<Weather />
</div>
);
}
}
export default App;
JSON endpoint goes here....
{
"coord": {
"lon": 13.41,
"lat": 52.52
},
"weather": [
{
"id": 803,
"main": "Clouds",
"description": "broken clouds",
"icon": "04n"
}
],
"base": "stations",
"main": {
"temp": 276.88,
"feels_like": 268.47,
"temp_min": 275.37,
"temp_max": 278.15,
"pressure": 994,
"humidity": 80
},
"visibility": 10000,
"wind": {
"speed": 9.3,
"deg": 240,
"gust": 14.4
},
"clouds": {
"all": 75
},
"dt": 1580260557,
"sys": {
"type": 1,
"id": 1275,
"country": "DE",
"sunrise": 1580280826,
"sunset": 1580312685
},
"timezone": 3600,
"id": 2950159,
"name": "Berlin",
"cod": 200
}
As content is an array type you can access coord or base directly. Instead change it to an object or access it based on array index like this.
this.state.content[0].coord / this.state.content[1].base
If you change content to object type you can access coord or base directly as i did it here
sample code:
state = {
content: { coord: "", base: "" }
};
after request fetch you can update state something like this.
this.setState({
content: { coord: res.data.coord, base: res.data.base }
});
You can make your state look like below which make reading and accessing the data easier.
state = {
content: {
coord: "",
base: "",
},
}
and your setState like below:
this.setState({
content: {
coord: res.data.coord,
base: res.data.base
}
})
I am successful in getting the data from the sample code in the below tutorial with Redux.
https://codepen.io/stowball/post/a-dummy-s-guide-to-redux-and-thunk-in-react
Below is the format used in the tutorial which works great.
[
{
"id": 1,
"label": "List item 1"
},
{
"id": 2,
"label": "List item 2"
},
{
"id": 3,
"label": "List item 3"
},
{
"id": "4",
"label": "label 4"
},
{
"id": "5",
"label": "label 5"
}
]
But I tried several ways and unable to pass the data in the format below
{
"banner": [
{ "key": "product", "id": "84535", "image_url": "/media/emthemes/slideshow/s/u/sultry-app_12.jpg" },
{ "key": "category", "id": "2629", "image_url": "/media/emthemes/slideshow/l/i/limecrime-app.jpg" },
{ "key": "product", "id": "84654", "image_url": "/media/emthemes/slideshow/a/m/ameera-app-banner.jpg" }
]
}
Current Reducer and mapping component in another file :
export function items(state = [], action) {
switch (action.type) {
case 'ITEMS_FETCH_DATA_SUCCESS':
return action.items;
default:
return state;
}
}
return (
<ul>
{this.props.items.map((item) => (
<li key={item.id}>
{item.id}
</li>
))}
</ul>
);
Tried with below changes in reducer:
export function items(state = {banner:[]}, action) {
switch (action.type) {
case 'ITEMS_FETCH_DATA_SUCCESS':
return action.items;
default:
return state;
}
}
change reducer to this:
{this.props.items.banner.map((item) => (
<li key={item.id}>
{item.id}
{item.key}
{item.image_url}
</li>
))}
And change the PropTypes of items in ItemList.js
items: PropTypes.object.isRequired
I have tried the tutorial and created a working example here:
https://github.com/stackOverflow166/redux-nwb
Edit2:
Cannot read property 'map'
This is problem is about the date type.Add this to the ItemList.js to change the date type to array.Only array has the map function.
let bannerArray = []
let banner = this.props.items.banner
for (let key in banner){
bannerArray.push(banner[key])
}