Reputation: 2290
How can I get the below API to display each date
and rate
from the JSON in a list? I have gone through the JSON and from what I can see I have mapped it correctly, yet {this.state.calendarDay}
is undefined in the console, causing the .map
to be undefined.
What am I missing?
import React, { Component } from 'react';
class Rates extends Component {
constructor(props) {
super(props);
this.state = {
fetched: false,
isLoaded: false,
calendarDay: []
}
}
componentWillMount(){
this.setState({
loading : true
});
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = `//apac.littlehotelier.com/api/v1/properties/chatelainevalleydirect/rates.json`;
fetch(proxyurl + url).then(res => res.json())
.then(res =>{
this.setState({
calendarDay : res.rate_plans,
loading : true,
fetched : true
});
});
}
render() {
const {fetched, loading, calendarDay} = this.state;
let content;
if(fetched){
content =
<ul>
{calendarDay.rate_plan_dates.map((dailyRates,index) => <li key={index+1}>{dailyRates.date} - ${dailyRates.rate}</li>)}
</ul>;
}
else if(loading && !fetched){
content = <p> Loading ...</p>;
}
else{
content = <div/>;
}
return (
<div>
{content}
</div>
);
}
}
export default Rates;
Upvotes: 2
Views: 592
Reputation: 2146
Call the api in ComponentDidMount and also I have split the code based on plan name.Hope this helps.
class Rates extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
calendarDay: []
}
}
componentDidMount(){
this.setState({
loading : true
});
var self = this;
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = `//apac.littlehotelier.com/api/v1/properties/chatelainevalleydirect/rates.json`;
fetch(proxyurl + url).then(res => res.json())
.then(res =>{
console.log(res)
self.setState({
calendarDay : res,
loading : false,
});
});
}
render() {
return (
<div>
{this.state.loading &&
<p>Loading...</p>
}
{(this.state.calendarDay.length == 0 && !this.state.loading) &&
<p>No data Available</p>
}
{this.state.calendarDay.length > 0 &&
<ul>
{this.state.calendarDay.map(function(i,index){
return(
<li key={index}>
{i.rate_plans.map(function(j,index){
return(
<ul key={index}> <p>{j.name}</p>
{j.rate_plan_dates.map(function(dailyRates,index){
return(
<li key={index+1}>{dailyRates.date} - ${dailyRates.rate}</li>
)
})}
</ul>
)
})}
</li>
)
})
}
</ul>
}
</div>
);
}
}
Upvotes: 0
Reputation: 6587
Couple of problems I see
First you specified that calendarDay: []
is an array and at the same time you are mapping through its property which makes no sense
{calendarDay.rate_plan_dates.map...
So what it is currently looks like array[].property
is always undefined.
Since calendarDay
is an array so it will not have a direct property rate_plans
.
one of your comments
when console.log(this.state.calendarDay) is placed after setState I get calendarDay is
undefined
. Cheers again for you help - any suggestions?
if you put log immediately after setting up the state it will not work as expected because state
in react works in asynchronous mode.
verify by the callback -
this.setState({
calendarDay: res,
loading: true,
fetched: true
}, () => console.log(this.state.calendarDay));
if
it is still undefined then res.rate_plans
is coming undefined from the server.
else do the followings as @Kamran Nazir already mentioned in his answer.
{calendarDay.map((item, k) => <div key={k}>
{item
.rate_plans
.map((ratePlans, ratePlanKey) => <ul key={ratePlanKey}>
{ratePlans
.rate_plan_dates
.map((dailyRates, index) => <li key={index + 1}>{dailyRates.date}
- ${dailyRates.rate}</li>)}
</ul>)}
</div>)}
Upvotes: 0
Reputation: 692
You are using nested array of objects. Here's a rough solution that I made.
this.setState({
calendarDay : res, // change this
loading : true,
fetched : true
});
inside the render function
if(fetched){
content =
<div>
{calendarDay.map((item, k) =>
<div key={k} >
{item.rate_plans.map((ratePlans, ratePlanKey)=>
<ul key={ratePlanKey}>
{ratePlans.rate_plan_dates.map((dailyRates,index) => <li key={index+1}>{dailyRates.date} - ${dailyRates.rate}</li>)}
</ul>
)}
</div>
)}
</div>
}
Upvotes: 1