I am trying to map through some data and display the values from the objects I am mapping through, but it keeps return "[object Object]", usually I just wrap it in JSON.stringify but that isn't working here, what am I doing wrong? Here's my code:
const ListingItem = (props: any) => {
const MOVIE_POSTER_API_URL = "https://image.tmdb.org/t/p/w92/";
const [openMovieDbData, setOpenMovieDbData] = useState<Array<any>>([]);
const [openMovieDbRatings, setOpenMovieDbRatings] = useState([]);
useEffect((): any => {
axios.get(`http://www.omdbapi.com/?t=${props.movie.title}&y=${props.movie.release_date && props.movie.release_date.substr(0, 4)}&apikey=${process.env.REACT_APP_OPEN_MOVIE_API_KEY}`)
.then(response => {
setOpenMovieDbData(response.data);
setOpenMovieDbRatings(response.data.Ratings);
})
.catch((error) => console.log('Open Movie DB HTTP GET Request Error response:', error))
}, [])
return (
<ListItem key={props.movie.id}>
{props.movie.backdrop_path ?
<ListItemAvatar>
<Avatar src={MOVIE_POSTER_API_URL + props.movie.backdrop_path} />
</ListItemAvatar> :
<ListItemIcon>
<Avatar>
<LocalMoviesIcon />
</Avatar>
</ListItemIcon>
}
<ListItemText
primary={props.movie.title}
secondary={`${props.movie.overview} Released in ${props.movie.release_date ? props.movie.release_date.substr(0, 4) : 'N/A'}
${openMovieDbRatings ? openMovieDbRatings.map((rating: any) => <div>{JSON.stringify(rating.Source)}: {JSON.stringify(rating.Value)}</div>) : 'No Reviews'}
Rated: ${openMovieDbData['Rated'] ? openMovieDbData['Rated'] : 'N/A'}
`
}
/>
</ListItem>
)
}
This is an example of what will get returned, in place of [object Object] should be the object values I am trying to access:
Example of response data:
{
"Title": "Braveheart",
"Year": "1995",
"Rated": "R",
"Released": "24 May 1995",
"Runtime": "178 min",
"Genre": "Biography, Drama, History, War",
"Director": "Mel Gibson",
"Writer": "Randall Wallace",
"Actors": "James Robinson, Sean Lawlor, Sandy Nelson, James Cosmo",
"Plot": "Scottish warrior William Wallace leads his countrymen in a rebellion to free his homeland from the tyranny of King Edward I of England.",
"Language": "English, French, Latin, Scottish Gaelic, Italian",
"Country": "USA",
"Awards": "Won 5 Oscars. Another 28 wins & 33 nominations.",
"Poster": "https://m.media-amazon.com/images/M/MV5BMzkzMmU0YTYtOWM3My00YzBmLWI0YzctOGYyNTkwMWE5MTJkXkEyXkFqcGdeQXVyNzkwMjQ5NzM#._V1_SX300.jpg",
"Ratings": [{
"Source": "Internet Movie Database",
"Value": "8.3/10"
}, {
"Source": "Rotten Tomatoes",
"Value": "78%"
}, {
"Source": "Metacritic",
"Value": "68/100"
}],
"Metascore": "68",
"imdbRating": "8.3",
"imdbVotes": "944,923",
"imdbID": "tt0112573",
"Type": "movie",
"DVD": "N/A",
"BoxOffice": "N/A",
"Production": "Icon Entertainment International, Twentieth Century Fox, Ladd Company, Paramount Pictures, B.H. Finance C.V.",
"Website": "N/A",
"Response": "True"
}
i think the issue is here,
secondary={`${props.movie.overview} Released in ${props.movie.release_date ? props.movie.release_date.substr(0, 4) : 'N/A'}
${openMovieDbRatings ? openMovieDbRatings.map((rating: any) => <div>{JSON.stringify(rating.Source)}: {JSON.stringify(rating.Value)}</div>) : 'No Reviews'}
Rated: ${openMovieDbData['Rated'] ? openMovieDbData['Rated'] : 'N/A'}
`}
#1: (main)
${openMovieDbRatings
? openMovieDbRatings.map((rating: any) =>
<div>{JSON.stringify(rating.Source)}: {JSON.stringify(rating.Value)}</div>
)
: 'No Reviews'}
You are mapping openMovieDbRatings and making em ReactElements (aka Objects) by wrapping those inside divs. But, Then u directly pass them to string. This is causing the [object object] thing
#2:
The Rating Object,
"Ratings": [{
"Source": "Internet Movie Database",
"Value": "8.3/10"
}, {
"Source": "Rotten Tomatoes",
"Value": "78%"
}, {
"Source": "Metacritic",
"Value": "68/100"
}],
Here, The Rating Value & Source are strings. So, it unnecessary to JSON.stringify them,
<div>{JSON.stringify(rating.Source)}: {JSON.stringify(rating.Value)}</div>
My Solution,
<ListItemText
primary={props.movie.title}
secondary={
<>
{props.movie.overview} Released in{' '}
{props.movie.release_date
? props.movie.release_date.substr(0, 4)
: 'N/A'}{' '}
{openMovieDbRatings
? openMovieDbRatings.map((rating: any) => (
<div>
{rating.Source}: {rating.Value}
</div>
))
: 'No Reviews'}
Rated:{' '}
{openMovieDbData['Rated'] ? openMovieDbData['Rated'] : 'N/A'}
</>
}
/>
Simply, use React.Fragments.
Related
I want to fetch data from API and trying to use in index.js
Error:
TypeError: Cannot read properties of undefined (reading 'icon')
When I console.log it prints
Empty Array of index.js > response data of weatherSlice.js > and finally response data of index.js as an array
I was getting undefined error and tried this and kinda worked .
{getCity.length !== 0 && (
<Typography variant="h6" component="div">
<div>Wind : {getCity.current.gust_kph} kph</div>
<div>Pressure: {getCity.current.pressure_in} in</div>
</Typography>
)}
But this time it gives same error on this block
{getCity.length !== 0 && (
<Grid item xs={3} sx={{mb:3}}>
<div className="label">{getDate()}</div>
<div className="label"> <img src={`${getCity.forecast.forecastday[1].condition.icon}`} alt="" /></div> // Gives undefined (reading"icon")
<div className="label" >22 C</div>
</Grid>)}
Index.js
const dispatch = useDispatch();
const [selectedCity, setSelectedCity] = useState('Ankara');
const getCity = useSelector((state) => state.weather.item);
const [datee , setDate ] = useState('');
useEffect(() => {
dispatch(fetchDefault(selectedCity))
setDate(getDate())
}, [dispatch])
weatherSlice
export const fetchDefault = createAsyncThunk('weather/getWeather', async (selectedCity) => {
const res = await axios(`http://api.weatherapi.com/v1/forecast.json?key=ebb6c0feefc646f6aa6124922211211&q=${selectedCity}&days=10&aqi=no&alerts=no
`)
return res.data});
export const weatherSlice = createSlice({
name: "weather",
initialState : {
item : [],
},
reducers:{},
extraReducers:{
[fetchDefault.fulfilled]: (state , action) => {
state.item = action.payload;
console.log(state.item)
},
[fetchDefault.pending]: (state , action) => {
console.log("sadsad")
}
}
After the state.weather.item state is populated it's now an object, not an array. The initial condition getCity.length !== 0 works/passes because getCity.length is undefined and undefined !== 0 evaluates true. The issue is occurring after you start accessing into the state.
The fetched city data is an object with location, current, and forecast properties.
// 20211114135700
// https://api.weatherapi.com/v1/forecast.json?key=ebb6c0feefc646f6aa6124922211211&q=seattle&days=10&aqi=no&alerts=no
{
"location": {
"name": "Seattle",
"region": "Washington",
"country": "United States of America",
"lat": 47.61,
"lon": -122.33,
"tz_id": "America/Los_Angeles",
"localtime_epoch": 1636927019,
"localtime": "2021-11-14 13:56"
},
"current": {
"last_updated_epoch": 1636926300,
"last_updated": "2021-11-14 13:45",
"temp_c": 16.1,
"temp_f": 61.0,
"is_day": 1,
"condition": {
"text": "Light rain",
"icon": "//cdn.weatherapi.com/weather/64x64/day/296.png",
"code": 1183
},
"wind_mph": 13.6,
"wind_kph": 22.0,
"wind_degree": 190,
"wind_dir": "S",
"pressure_mb": 1014.0,
"pressure_in": 29.94,
"precip_mm": 1.0,
"precip_in": 0.04,
"humidity": 90,
"cloud": 100,
"feelslike_c": 16.1,
"feelslike_f": 61.0,
"vis_km": 3.2,
"vis_miles": 1.0,
"uv": 4.0,
"gust_mph": 18.8,
"gust_kph": 30.2
},
"forecast": {
"forecastday": [
{
"date": "2021-11-14",
"date_epoch": 1636848000,
"day": {
"maxtemp_c": 16.2,
"maxtemp_f": 61.2,
"mintemp_c": 11.5,
"mintemp_f": 52.7,
"avgtemp_c": 14.9,
"avgtemp_f": 58.8,
"maxwind_mph": 16.1,
"maxwind_kph": 25.9,
"totalprecip_mm": 21.1,
"totalprecip_in": 0.83,
"avgvis_km": 9.3,
"avgvis_miles": 5.0,
"avghumidity": 93.0,
"daily_will_it_rain": 1,
"daily_chance_of_rain": 99,
"daily_will_it_snow": 0,
"daily_chance_of_snow": 0,
"condition": {
"text": "Heavy rain",
"icon": "//cdn.weatherapi.com/weather/64x64/day/308.png",
"code": 1195
},
"uv": 1.0
},
"astro": {
...
},
"hour": [
...
]
},
...
]
}
}
You are attempting to render the forecast, but here's where the code really goes sideways. You're assuming there's at least 2 elements (i.e. the getCity.forecast.forecastday.length>= 2), and then if there is, assume theres aconditionproperty. When there isn't andgetCity.forecast.forecastday[1].condition` is undefined, this is the error you are seeing.
From what I can tell, the condition property is nested within a day field. Since it's unclear what properties are guaranteed to exist in the response data your best bet is to:
First make sure you are accessing into the correct path
Use null-checks/guard-clauses or Optional Chaining operator to prevent accidental null/undefined accesses
The updated object property path is as follows:
getCity.forecast.forecastday.[1].day.condition.icon
If any of these are potentially undefined or otherwise not returned in the data, the corrected access using the Optional Chaining operator is as follows:
getCity.forecast?.forecastday?.[1]?.day?.condition?.icon
Which is the equivalent null-check/guard-clause version of:
getCity.forecast
&& getCity.forecast.forecastday
&& getCity.forecast.forecastday[1]
&& getCity.forecast.forecastday[1].day
&& getCity.forecast.forecastday[1].day.condition
&& getCity.forecast.forecastday[1].day.condition.icon
Use the same sort of check for the current weather data:
{getCity.current && (
<Typography variant="h6" component="div">
<div>Wind : {getCity.current.gust_kph} kph</div>
<div>Pressure: {getCity.current.pressure_in} in</div>
</Typography>
)}
Finally, update the initial state for the weather slice to match the data invariant, it should be an object.
initialState : {
item : {},
},
I am stuck and need help finishing this fetch request.
I need a function to check if the movie (a single object) in the request has previously been rated by the user.
The ratings are in the ratedMovies array. If the movie was rated I need the userRating property with it's value to be added to the response. If it has not been rated, I need the userRating value to be null
const ratedMovies = useStore((state) => state.ratedMovies)
const getMovieDetails = () => {
const key = `https://www.omdbapi.com/?i=${movie.imdbID}&apikey=b46dc190`
axios
.get(key)
.then((response) => {
// Here a comparison is required, to check if the movie in the response (a single object)
// has ever been rated before and its ID (imdbID) and userRating (property to be added) is
// present in the ratedMovies array
// if it is present I need the property userRating nad it's value to be added to the response
// or when it is empty, to have the userRating be null
setModalDetails(response.data)
})
.then((response) => {
console.log(modalDetails)
})
.catch((error) => console.log(error))
}
Sample axios response:
{
"Title": "Star Wars: Episode V - The Empire Strikes Back",
"Year": "1980",
"Rated": "PG",
"Released": "20 Jun 1980",
"Runtime": "124 min",
"Genre": "Action, Adventure, Fantasy",
"Director": "Irvin Kershner",
"Writer": "Leigh Brackett, Lawrence Kasdan, George Lucas",
"Actors": "Mark Hamill, Harrison Ford, Carrie Fisher",
"Plot": "After the Rebels are brutally overpowered by the Empire on the ice planet Hoth, Luke Skywalker begins Jedi training with Yoda, while his friends are pursued across the galaxy by Darth Vader and bounty hunter Boba Fett.",
"Language": "English",
"Country": "United States, United Kingdom",
"Awards": "Won 2 Oscars. 25 wins & 20 nominations total",
"Poster": "https://m.media-amazon.com/images/M/MV5BYmU1NDRjNDgtMzhiMi00NjZmLTg5NGItZDNiZjU5NTU4OTE0XkEyXkFqcGdeQXVyNzkwMjQ5NzM#._V1_SX300.jpg",
"Ratings": [
{
"Source": "Internet Movie Database",
"Value": "8.7/10"
},
{
"Source": "Rotten Tomatoes",
"Value": "94%"
},
{
"Source": "Metacritic",
"Value": "82/100"
}
],
"Metascore": "82",
"imdbRating": "8.7",
"imdbVotes": "1,209,128",
"imdbID": "tt0080684",
"Type": "movie",
"DVD": "21 Sep 2004",
"BoxOffice": "$292,753,960",
"Production": "N/A",
"Website": "N/A",
"Response": "True"
}
Sample rating:
ratedMovies = [{imdbID: 'tt0080684', userRating: 8}]
Ok if I understand it correctly it goes like this:
let data = response.data;
let newMovieId = data.imdbID;
ratedMovies.forEach((movie) => {
if(movie.imdbID === newMovieId) {
data.userRating = movie.userRating;
}
});
setModalDetails(data)
code above goes inside the axios success callback
You can use .filter function like this:
ratedMovies = [{imdbID: 'tt0080684', userRating: 8}]
notratedMovies = [{imdbID: 'tt0080111', userRating: 8}]
let result = ratedMovies.filter(obj => {
return obj.imdbID === imdb.imdbID
});
console.log(result);
let notresult = notratedMovies.filter(obj => {
return obj.imdbID === imdb.imdbID
});
console.log(notresult);
I'm having some trouble rendering an image onto a section list from a JSON file even though I am having no trouble with the text data.
here is my JSON DATA:
{
"title" : "Friday",
"data":
[
{
"artist": "artist 1",
"stage": "The Oak",
"Instagram": "insta",
"Spotify": "spot",
"date": "10/8/2021",
"Image": "../assets/art1.jpg",
"Time" : "4:30PM - 5:00 PM"
},
{
"artist": "artist 2",
"stage": "The Oak",
"Instagram": "insta",
"Spotify": "spot",
"date": "10/8/2021",
"Image": "../assets/art2.jpg",
"Time" : "5.00PM - 5:30 PM"
}
]},
I am aware that you have to use the require function to render it but I just cant seem to get it right.
Here is the SectionList:
<SectionList
sections={data}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => (<View style={styles.listItemView}>
<Image style={styles.image} source={require(item.Image)} />
<View>
<Text style={styles.listItem}>{item.artist}</Text>
<Text style={styles.listItemTime} >{item.Time}</Text>
</View>
</View>)}
renderSectionHeader={({ section }) => (
<View style={styles.item}>
<Text style={styles.title}>{section.title}</Text>
</View>)}
/>
Any help is welcome. Please let me know if I need to add addition info!
Thanks!
You can use a if-else or switch statement to get the image you want to use.
const getArtImage = (artName) => {
switch (artName){
case 'art1':
return require('../assets/art1.jpg');
case 'art2':
return require('../assets/art2.jpg');
default:
return require('../assets/defaultArt.jpg');
}
}
and use this getArtImage function in your Image component.
<Image style={styles.image} source={getArtImage(item.Image)} />
item.Image should be like art1, art2 etc.
--
If your json is a local file, you can convert it to a js file.
export default {
title: "Friday",
data: [
{
artist: "artist 1",
stage: "The Oak",
Instagram: "insta",
Spotify: "spot",
date: "10/8/2021",
Image: require("../assets/art1.jpg"),
Time: "4:30PM - 5:00 PM",
},
{
artist: "artist 2",
stage: "The Oak",
Instagram: "insta",
Spotify: "spot",
date: "10/8/2021",
Image: require("../assets/art2.jpg"),
Time: "5.00PM - 5:30 PM",
},
],
};
I have a JSON request, that returns a JSON objects;
{
"kind": "youtube#searchListResponse",
"etag": "zy8y9DkaOiYwKh0aStoEqOU_knU",
"nextPageToken": "CBQQAA",
"regionCode": "GB",
"pageInfo": {
"totalResults": 40,
"resultsPerPage": 20
},
"items": [
{
"kind": "youtube#searchResult",
"etag": "tvnouv0ap06XQKjt95dVECc_VZ4",
"id": {
"kind": "youtube#video",
"videoId": "Qiyk-s60rgo"
},
"snippet": {
"publishedAt": "2020-04-30T10:00:46Z",
"channelId": "UCa_6KiOjxm6dEC_mMRP5lGA",
"title": "Derby Futsal Club - Goal of the Season 2019/20 | Tom Gascoyne vs Birmingham",
"description": "Derby Futsal Club's Goal of the Season as voted for by the public went to Tom Gascoyne for his goal against Birmingham in the National Futsal Series on 3rd ...",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/Qiyk-s60rgo/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/Qiyk-s60rgo/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/Qiyk-s60rgo/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "Derby Futsal",
"liveBroadcastContent": "none",
"publishTime": "2020-04-30T10:00:46Z"
}
},
I'm reading the JSON like so;
useEffect(() => {
fetch(playertype(typeOfProfile))
.then((response) => response.json())
.then((json) => {
setData(json)
})
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
return (
<View style={styles.body}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data[0]}
horizontal={true}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<View style={stylesB.container}>
<Image style={styles.img} source={{ uri: chkValueI(item.items.snippet.medium.url) }} />
</View>
)}
/>
)}
</View>
);
};
I'm reading the data as data[0] so I hit the first object, and then finding the property I want (the image) by using item.items.snippet.medium.url, but this doesn't return anything.
My question is;
Can I specify the object I want to get by using data[0] and then reference a property using item.items.snippet.medium.url?
Can I specify the object I want to get by using data[0] and then
reference a property using item.items.snippet.medium.url?
Flat list requires a data array so you dont need a flatlist to display a single item. You can simply use the renderItem function and pass the first item.
item.items.snippet.medium.url
Here the items is an array so you should use something like below to access the item. Better check the array length before doing this. Or go for a map to map the values.
item.items[0].snippet.medium.url
Hope this helps.
For some reason I'm unable to access the "question" key within the results array. Could someone help please? This is just a side project I've started and have been tearing my hair out for hours trying to get this first basic part to work. I've only been using react and API's for about a week now and I'm super inexperienced, so any help would be appreciated.
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
constructor() {
super()
this.state = {
questionList: []
}
}
componentDidMount() {
fetch('https://opentdb.com/api.php?amount=10')
.then(resp => resp.json())
.then(resp => this.setState({ questionList: resp }))
}
render() {
return (
<div>{this.state.questionList.results[0].question}</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
and here's the API data -
{
"response_code": 0,
"results": [
{
"category": "Entertainment: Film",
"type": "multiple",
"difficulty": "medium",
"question": "Which of the following James Bond villains is not affiliated with the SPECTRE organization?",
"correct_answer": "Auric Goldfinger",
"incorrect_answers": [
"Dr. Julius No",
"Rosa Klebb",
"Emilio Largo"
]
},
{
"category": "Geography",
"type": "multiple",
"difficulty": "hard",
"question": "The mountainous Khyber Pass connects which of the two following countries?",
"correct_answer": "Afghanistan and Pakistan",
"incorrect_answers": [
"India and Nepal",
"Pakistan and India",
"Tajikistan and Kyrgyzstan"
]
},
{
"category": "Entertainment: Video Games",
"type": "multiple",
"difficulty": "medium",
"question": "In Team Fortress 2, which class wields a shotgun?",
"correct_answer": "Everyone Listed",
"incorrect_answers": [
"Heavy",
"Soldier",
"Engineer"
]
},
{
"category": "Entertainment: Video Games",
"type": "multiple",
"difficulty": "easy",
"question": "Who is the leader of Team Mystic in Pokémon Go?",
"correct_answer": "Blanche",
"incorrect_answers": [
"Candela",
"Spark",
"Willow"
]
},
{
"category": "Science & Nature",
"type": "multiple",
"difficulty": "easy",
"question": "The medical term for the belly button is which of the following?",
"correct_answer": "Umbilicus",
"incorrect_answers": [
"Nevus",
"Nares",
"Paxillus"
]
},
{
"category": "Entertainment: Cartoon & Animations",
"type": "multiple",
"difficulty": "easy",
"question": "What is lost in Hawaiian and is also the name of a little girl in a 2002 film which features a alien named "Stitch"?",
"correct_answer": "Lilo",
"incorrect_answers": [
"Lolo",
"Lucy",
"Lulu"
]
},
{
"category": "Entertainment: Cartoon & Animations",
"type": "multiple",
"difficulty": "hard",
"question": "In "Gravity Falls", what does Quentin Trembley do when he is driven out from the White House?",
"correct_answer": "Eat a salamander and jump out the window.",
"incorrect_answers": [
"Leave in peace.",
"Jump out the window.",
"Release 1,000 captive salamanders into the white house."
]
},
{
"category": "Entertainment: Television",
"type": "multiple",
"difficulty": "hard",
"question": "Who was the winner of "Big Brother" Season 10?",
"correct_answer": "Dan Gheesling",
"incorrect_answers": [
"Bryce Kranyik",
"Ryan Sutfin",
"Chris Mundorf"
]
},
{
"category": "General Knowledge",
"type": "multiple",
"difficulty": "easy",
"question": "Terry Gilliam was an animator that worked with which British comedy group?",
"correct_answer": "Monty Python",
"incorrect_answers": [
"The Goodies",
"The League of Gentlemen",
"The Penny Dreadfuls"
]
},
{
"category": "Entertainment: Video Games",
"type": "multiple",
"difficulty": "easy",
"question": "In Counter-Strike: Global Offensive, what's the rarity of discontinued skins called?",
"correct_answer": "Contraband",
"incorrect_answers": [
"Discontinued",
"Diminshed",
"Limited"
]
}
]
}
Thanks!
This will surely fail, since you are calling an asynchronous action, but your render relies on that explicitly:
{this.state.questionList.results[0].question}
You are probably receiving Cannot read property 'question' of undefined
or
Cannot read property '0' of undefined
The most basic solution would be to check if the questionList actually has some data inside.
Note: questionList in an array, not an object.
render() {
if (this.state.questionList.length === 0) {
return null;
}
return (
<div>{this.state.questionList[0].results[0].question}</div>
);
}
However the best, but the longest solution would be check step-by-step that questionList has a correct structure:
{this.state.questionList[0]
&& this.state.questionList.results
&& this.state.questionList.results[0]
&& this.state.questionList.results[0].question}
As other's have noted, your API call will take a period of time, and your App will render before it is done, so your data isn't there yet when it goes to render. You're basically trying to get data that doesn't exist yet.
I like to have a loading flag on my state to show loading stuff, as well an an error flag for any errors that come in.
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
constructor() {
super()
this.state = {
questionList: {
isLoading: true,
error: null,
data: null,
}
}
}
componentDidMount() {
fetch('https://opentdb.com/api.php?amount=10')
.then(resp => resp.json())
.then(resp => this.setState(
{questionList:
{data: resp, isLoading: false, error: null}
}))
.catch(e => this.setState({questionList: {data: null, error: e, data: null}}))
}
render() {
if (this.state.questionList.isLoading)
return <Loading />
if (this.state.questionList.error)
return <Error error={this.state.questionList.error} />
return (
<div>{this.state.questionList.data.results[0].question}</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
You can and should be a little smarter with your checks, and data fixing, etc, etc... but that is the gist of how I deal with it.
I also recommend wrapping up your API calls in a module. So you could say api.questions.getList().then(...) instead of having the fetch in your components, and any data conversions, or other ugly stuff can be put in those modules. It isn't really related to your question (and would probably be overkill for this anyways), but since you seem to new to react I'll throw that out there for you.
use
console.log in render()
and you will see that your state is empty, because you call async function.
There is:
Api call - it can take 1 sec, 10 sec, 20 sec etc...
call render() - your state is empty because you need to wait for API response
you will get error...
You can add some code, eg:
render() {
if (this.state.questionList.length === 0) {
return '<div>Loading...</div>';
}
return (
<div>{this.state.questionList.results[0].question}</div>
)
}
I am not sure that your results are back to the component by the time it renders. I think you need to run a check to see if the results are there. Can you try something like this and we can go from here?
{this.state.questionList.results.length > 1 && this.state.questionList.results[0].question}