Fetch specific data from API ReactJS - javascript

I'm trying to fetch specific data from a API, something like that:
I have that JSON after response:
{
"id": 5,
"url": "http://127.0.0.1:8000/api/article/5/",
"title": "Obama Offers Hopeful Vision While Nothing Nation's Fears",
"description": "Obama Offers Hopeful Vision While Nothing Nation's Fears",
"category": [
"http://127.0.0.1:8000/api/category/1/"
],
"image": "http://127.0.0.1:8000/media/article_image/news_01_3MT46Rk.jpg"
},
{
"id": 6,
"url": "http://127.0.0.1:8000/api/article/6/",
"title": "NASA Formalizes Efforts To Protect Earth From Asteroids",
"description": "Last week, NASA annouced a new program called the Planetary Defense Coordination Office (PDCO) which will coordinate NASA's efforts for detecting and tracking near-Earth objects (NEOs), If a large object comes hurting toward our planet...",
"category": [
"http://127.0.0.1:8000/api/category/4/"
],
"image": "http://127.0.0.1:8000/media/article_image/news_03_EOUms51.jpg"
},
{
"id": 7,
"url": "http://127.0.0.1:8000/api/article/7/",
"title": "Didi Kuaidi, The Company Beating Uber In China, Opens Its API To Third Party Apps",
"description": "One day after Uber updated its API to add 'content experiences' for passengers, the U.S company's biggest rival - Didi Kuadii in China - has opened its own platform up by releasing an SDK for developoers and third-parties",
"category": [
"http://127.0.0.1:8000/api/category/3/"
],
"image": "http://127.0.0.1:8000/media/article_image/news_02_l5zY4HJ.jpg"
}
And in that API, i have a child called by Category:
{
"id": 1,
"url": "http://127.0.0.1:8000/api/category/1/",
"name": "POLITICS"
},
{
"id": 2,
"url": "http://127.0.0.1:8000/api/category/2/",
"name": "BUSINESS"
},
{
"id": 3,
"url": "http://127.0.0.1:8000/api/category/3/",
"name": "TECH"
},
{
"id": 4,
"url": "http://127.0.0.1:8000/api/category/4/",
"name": "SCIENCE"
},
{
"id": 5,
"url": "http://127.0.0.1:8000/api/category/5/",
"name": "SPORTS"
}
What i want to do is to render my articles with the POLITICS category, but I'dont know how to do that, Here is what I've done so far.
Method to fetch json:
getItems() {
this.setState({ 'isLoading': true });
fetch('http://127.0.0.1:8000/api/article/')
.then(results => {
if (results.ok) {
return results.json();
} else {
throw new Error('Something went wrong ...');
}
})
.then(results => this.setState({ 'items': results, 'isLoading': false }))
.catch(error => this.setState({ error, isLoading: false }));
}
My render method:
render() {
const { isLoading, error } = this.state;
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return <p>Loading ...</p>;
}
return (
<ul>
{this.state.items.map(function (item, index) {
console.log(item.category.indexOf("1") != 01)
if (item.category === 1){
return <ContentItem item={item} key={index} />
}
})}
</ul>
);
}
EDIT: Output from console.log(item) in render:
{id: 5, title: "Obama Offers Hopeful Vision While Nothing Nation's Fears", description: "Obama Offers Hopeful Vision While Nothing Nation's Fears", category: Array(1), image: "http://127.0.0.1:8000/media/article_image/news_01_3MT46Rk.jpg"}
category: Array(1)
0: 1
length: 1
__proto__: Array(0)
description: "Obama Offers Hopeful Vision While Nothing Nation's Fears"
id: 5
image: "http://127.0.0.1:8000/media/article_image/news_01_3MT46Rk.jpg"
title: "Obama Offers Hopeful Vision While Nothing Nation's Fears"
__proto__: Object

What you are NOT doing, is filtering by id,
if (item.category === 1){ //You need to add .id here
return <ContentItem item={item} key={index} />
}
like so:
if (item.category.id === 1){ //.id
return <ContentItem item={item} key={index} />
}
What you are doing wrong is that you are checking the whole object against the === 1 condition instead of just the property id of the object.

Related

Creating an new object from an existing object in javascript

I am going through a challenge from devchallenges.io, Shoppingify challenge. Having read the prompt, I proceeded to create a model which has the following format when a request is made.
{
"user": 1,
"_id": 3393220221,
"name": Chicken,
"category": "Meat",
"note": "This is an example note",
"image_url": "www.exampleurl.com"
}
The issue I'm having is that the component expects the object in the following format.
{
"category": "Meat",
"items": [
{
"user": 1,
"_id": "3393220221",
"name": "Chicken",
"note": "This is an example note",
"image_url": "www.exampleurl.com"
}
]
}
The link to the challenge is https://devchallenges.io/challenges/mGd5VpbO4JnzU6I9l96x for visual reference.
I'm struggling with how to modify the object response from the request. I want to be able to find occurances of the same category name and push the items onto a new object as shown.
const users = [
{
"user": 1,
"_id": 3393220221,
"name": "Chicken",
"category": "Meat",
"note": "This is an example note",
"image_url": "www.exampleurl.com"
}
];
function modifyUserObject(users) {
const result = {};
users.forEach(user => {
if (!result[user]) {
result[user] = {
category: user.category,
items: []
}
}
//code here..if want to remove user properties like user
result[user].items.push(user);
});
return Object.values(result);
}
modifyUserObject(users);
Hope this will be helpful! Happy coding...
The value Chicken is not defined. Is this a typing error by you? Anyway this should do the trick:
const obj = {
user: 1,
_id: 3393220221,
name: "Chicken",
category: "Meat",
note: "This is an example note",
image_url: "www.exampleurl.com",
};
function createObj(arg) {
let result = {
category: arg.category,
items: [
{
user: arg.user,
_id: arg._id,
name: arg.name,
note: arg.note,
image_url: arg.image_url,
},
],
};
return result;
}
console.log(createObj(obj));
Edit:
If you want to create a new object that is not related to the old one (deep copy) you need to do JSON.parse(JSON.stringify(obj)) to not change the values of the original object.

Looping through array, fetching tweets and returning new reversed array javascript react

UPDATE: I have deployed the site for more context you can view it here https://conundrum-quest-rw-rebuild-web.onrender.com/
the public repo is here
https://github.com/wispyco/conundrum-quest-rw-rebuild
Note: the data on the live site is different but the initial load is loading the hero's on the wrong cards, you can compare the quest with subsequent heros on the home page and the returned data from my function below, you can scroll down to see the rendered cards.
You can see that if you click on a card it shows the correct heros on the single page.
I have the following quests data structure that I am looping through in a separate function and running a fetch to request some profile images from twitter.
[
{
"__typename": "Quest",
"id": 5,
"name": "How do we solve mental health related issues?",
"userId": 17,
"heros": [
{
"__typename": "Hero",
"name": "Anders Kitson",
"twitter": "anderskitson"
},
{
"__typename": "Hero",
"name": "ders",
"twitter": "derz_O"
}
]
},
{
"__typename": "Quest",
"id": 6,
"name": "How do we create a world where North Korea participates and collaborates with the rest of the World?",
"userId": 17,
"heros": [
{
"__typename": "Hero",
"name": "Crypto Dude",
"twitter": "phunk2243"
}
]
}
]
Here is my custom hook
const twitter = useFetchTwitterMultipleQuests(quests)
export const useFetchTwitterMultipleQuests = (twitterProfileManyQuests) => {
const [twitter, setTwitter] = useState([])
useEffect(() => {
twitterProfileManyQuests.forEach(async (twitterProfileMany, i) => {
const woop = twitterProfileMany.heros.map(async (twitterProfile) => {
const test = fetch(
`${window.location.origin}/.redwood/functions/twitter`,
{
method: 'POST',
body: JSON.stringify({ twitter: twitterProfile.twitter }),
}
)
.then(function (response) {
// The response is a Response instance.
// You parse the data into a useable format using `.json()`
console.log('test')
return response.json()
})
.then(function (data) {
return data.data.resultAwaited.data
})
const go = await test
return go
})
const june = await Promise.all(woop)
setTwitter((prevState) => {
return [...prevState, june]
})
})
}, [twitterProfileManyQuests])
const reversedTwitter = twitter.reverse()
return reversedTwitter
}
The problem is the reversedTwitter or twitter variable in the end sometimes is in the correct reversed order and sometimes not reversed, and I can't figure out why.
This is the correct order result
[
[
{
"username": "anderskitson",
"profile_image_url": "https://pbs.twimg.com/profile_images/1428160652237889539/I7ZiM_g8_normal.jpg",
"name": "▲nders on a quest 🜸 to see myself 🪞",
"id": "4633808432"
},
{
"profile_image_url": "https://pbs.twimg.com/profile_images/1496985668043436033/NoyLrUys_normal.jpg",
"name": "ders.eth",
"id": "1389695824934834181",
"username": "derz_O"
}
],
[
{
"username": "phunk2243",
"profile_image_url": "https://pbs.twimg.com/profile_images/1536485988767350784/cfP_sPSC_normal.jpg",
"name": "9999999333 (🅱️uilding 35 Phunks) 🔜",
"id": "1355005208259133442"
}
]
]
This is the incorrect order result
[
[
{
"name": "9999999333 (🅱️uilding 35 Phunks) 🔜",
"profile_image_url": "https://pbs.twimg.com/profile_images/1536485988767350784/cfP_sPSC_normal.jpg",
"username": "phunk2243",
"id": "1355005208259133442"
}
],
[
{
"username": "anderskitson",
"profile_image_url": "https://pbs.twimg.com/profile_images/1428160652237889539/I7ZiM_g8_normal.jpg",
"name": "▲nders on a quest 🜸 to see myself 🪞",
"id": "4633808432"
},
{
"username": "derz_O",
"profile_image_url": "https://pbs.twimg.com/profile_images/1496985668043436033/NoyLrUys_normal.jpg",
"name": "ders.eth",
"id": "1389695824934834181"
}
]
]
The reason this matters is how I am rendering the data. I am rendering a Quest from the quests data, then mapping over the heros in a quest which correspond to the twitter profiles.
See Here
{quests.map((quest, i) => (
<QuestCard key={quest.id}>
<Link to={routes.quest({ id: quest.id })} key={quest.id}>
<div>
<h3>{truncate(quest.name)}</h3>
{quest.heros.map((hero, index) => (
<React.Fragment key={hero.id}>
{twitter.length > 0 && twitter[i] && (
<span>
{hero.name}
<p>{twitter[i][index]?.name}</p>
<img
key={i}
src={twitter[i][index]?.profile_image_url}
alt={twitter[i][index]?.name}
/>
</span>
)}
</React.Fragment>
))}
</div>
</Link>
<div className="clear" />
</QuestCard>
))}
Any help would be greatly appreciated, most of what I have done works, but after about three refreshes the ordering breaks. Thanks
Fixed by using a custom service and a custom sdl in redwood instead of using a function and having to create a custom hook for rendering. This was recommended by the RW team from this article
https://redwoodjs.com/docs/how-to/using-a-third-party-api
And you can see my changes here
https://github.com/wispyco/conundrum-quest-rw-rebuild/pull/8/commits/41637813dd50be70e2e89372606c08e39618fa07

Access data / Structure data in ReactJS / Firebase

I'm a little bit losted coming from Rails to React/Firebase. I have the following realtime database structure. As you can see, a product can have a brand and multiple sellers.
If a brand is true, i'd like to get / display the brand contents on my page (the avatar, name, link etc.). Same for the sellers.
Right now, if i try to display the brand content, i get "true" when i'd like an object containing the infos i've stored in brands or sellers.
So i'd like for example to be able to do something like this :
<p>{this.props.brands.name}</p> (it can only have one brand for now)
As for the sellers i'd like for example to be able to do something like this :
this.state.sellers.map((seller) =>
<div>
<img src={seller.avatar} />
<p>{seller.name}</p>
</div>
);
Here is my firebase realtime database structure (json) :
{
"products": {
"1": {
"name": "Nike HyperAdapt 1.0",
"tagline": "Self-lacing running shoes",
"releaseDate": "20.08.2020",
"brands": {
"Nike": true
},
"thumbnail": "/img/thumbnails/nike-hyperadapt-thumbnail.jpg",
"media": "/img/media/nike-hyperadapt-media-01.jpeg",
"isRaffle": true,
"description": "Nike HyperAdapt 1.0 is Nike's first line of shoes that can lace themselves, thanks to an internal cable system comprised of fishing line and a pressure sensor located in the sole that responds to the weight of your foot as you move with an algorithmic pressure equation.",
"upvote": "169",
"sellers": {
"Shop 01": true,
"Nike": true
}
},
"2": {
"name": "Puma Fi",
"tagline": "Self lacing shoes by Puma",
"releaseDate": "22.08.2020",
"brands": {
"Puma": true
},
"thumbnail": "/img/thumbnails/puma-fi-thumbnail.jpg",
"media": "/img/media/puma-fi-media-01.jpeg",
"isRaffle": true,
"description": "The technology platform Fit Intelligence (Fi) is designed to automate and finetune performance for our footwear. The very first Fi footwear style is a self-lacing training shoe made for workouts and light running.",
"upvote": "88",
"sellers": {
"Shop 01": true,
"Puma": true
}
}
},
"brands": {
"Nike": {
"name": "Nike",
"avatar": "/img/brands/nike-logo.png",
"link": "https://www.nike.com/fr",
"products": {
"1": true
}
},
"Puma": {
"name": "Puma",
"avatar": "/img/brands/puma-logo.png",
"link": "https://eu.puma.com/fr/fr/home",
"products": {
"2": true
}
}
},
"sellers": {
"Shop 01": {
"name": "Shop 01",
"avatar": "/img/sellers/shop-01-logo.png",
"link": "https://www.shop-01.com/",
"products": {
"1": true,
"2": true
}
},
"Nike": {
"name": "Nike",
"avatar": "/img/sellers/nike-store-logo.png",
"link": "https://www.nike.com/fr/launch",
"products": {
"1": true
}
},
"Puma": {
"name": "Puma",
"avatar": "/img/sellers/puma-logo.png",
"link": "https://eu.puma.com/fr/fr/home",
"products": {
"2": true
}
}
}
}
EDIT :
here is what the component that's supposed to show the data looks like :
import React, { Component } from 'react';
import ProductPopup from './ProductPopup';
class ProductItem extends Component {
constructor() {
super();
this.state = {
productPopupStatus: false,
};
}
showProductPopup = () => {
this.setState({ productPopupStatus: true });
};
hideProductPopup = () => {
this.setState({ productPopupStatus: false });
};
renderUpvoteBtn() {
return (
<div className="upvote-btn_wrapper">
<a className="upvote-btn" href="#">
<span className="upvote-counter">
<i className="fas fa-sort-up"></i>
<span>{this.props.upvote}</span>
</span>
</a>
</div>
);
}
renderInfoSession() {
return (
<section className="product-item-info">
<span>
<h2>{this.props.name}</h2>
</span>
<p>{this.props.tagline}</p>
<div className="product-item_meta-shadow"></div>
</section>
);
}
renderMeta() {
return (
<div className="product-item_meta">
<a href="#">
// SHOW ASSOCIATED BRAND AVATAR AND NAME
</a>
</div>
);
}
render() {
return (
<li className="product-item">
{this.renderUpvoteBtn()}
<a href="#" onClick={this.showProductPopup} className="product-item_content">
<img className="product-item-media" src={this.props.media} />
{this.renderInfoSession()}
</a>
{this.renderMeta()}
<ProductPopup status={this.state.productPopupStatus} hidePopup={this.hideProductPopup} />
</li>
);
}
}
export default ProductItem;
It seems like you're getting "true" because your brand name is a boolean. I think it might help by having your brand listed like:
brand: {
name: "Nike"
}
As far as your sellers, I feel that listing them in an array rather than an object would be better as well. You'll only be getting "true" because those values are boolean.
Is there a reason you wanted "sellers" to be an object? If not I would make it an array with objects that hold the info you need.
brands: [
{name: "Brand1", img: "imgsource1"},
{name: "Brand2", img: "imgsource2"}
]

How can I get all results in ReactiveList

I've tried to use on all data but it doesn't work since I can get only the number of results as stated in the 'size' parameter. Here part of my code.
<ReactiveList
componentId="results"
dataField="original_title"
size={1}
showResultStats={true}
pagination={true}
react={{
and: "searchbox"
}}
onAllData={this.onAllData}
/>
onAllData(shops) {
let result = null;
if (shops !== null) {
console.log(shops.length);
result = shops.map((marker) => (
<ListItem>
<Thumbnail square size={80} source={{ uri: 'https://dummyimage.com/80x80/000/fff' }} />
<Body>
<Text>{marker.name}</Text>
<Text note>{marker.dis}</Text>
</Body>
</ListItem>
))
return result;
}
}
There are a couple of ways you can go about this problem:
Rendering all results with infinite loading
onAllData will give the number of results specified in the size prop. Usually, its not a good idea to set a very high size since it will take more time fetching and rendering the results. A good alternative for this is to use infinite scrolling by setting the pagination prop to false and setting a value in size prop which tells the component how many results to fetch when you reach the end of the list.
Fetching all results using scroll API
tl;dr Demo
Note
This answer uses reactivesearch for web (for demonstration) but you can use the same props in reactivesearch-native since the API is same.
The above approach works fine if you're only interested in rendering the results. But if you wish to fetch all the results for the current query, you can use the scroll API from Elasticsearch. You can use ReactiveList to get the current query and then use it together with the scroll API.
For this purpose, you can make use of the onQueryChange prop on ReactiveList:
First specify an onQueryChange prop on the ReactiveList which receives the previous and current query as parameters:
onQueryChange={(prev, next) => ...}
This function will be invoked each time the query is changed so you can write a logic to fetch the hits for the current query (received in the next parameter) whenever required.
A scroll API call returns the results in the following format:
{
"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoAgAAAAClGlY4FlotbmJJZXA0U09lMlZFMUNyQ3M2M0EAAAAApRpWORZaLW5iSWVwNFNPZTJWRTFDckNzNjNB",
"took": 0,
"timed_out": false,
"_shards": {
"total": 2,
"successful": 2,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 9407,
"max_score": 1,
"hits": [
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5676",
"_score": 1,
"_source": {
"authors": "Arthur C. Clarke, Gentry Lee",
"average_rating": 3.76,
"average_rating_rounded": 4,
"books_count": 48,
"id": 5676,
"image": "https://images.gr-assets.com/books/1375814957l/112518.jpg",
"image_medium": "https://images.gr-assets.com/books/1375814957m/112518.jpg",
"isbn": "1857230213",
"language_code": "eng",
"original_publication_year": 1991,
"original_series": "Rama",
"original_title": "The Garden of Rama (Rama, #3)",
"ratings_count": 16389,
"title": "The Garden of Rama (Rama, #3)"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5681",
"_score": 1,
"_source": {
"authors": "Darren Shan",
"average_rating": 4.22,
"average_rating_rounded": 4,
"books_count": 52,
"id": 5681,
"image": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"image_medium": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"isbn": "",
"language_code": "",
"original_publication_year": 2003,
"original_series": "Cirque Du Freak",
"original_title": "Killers of the Dawn (Cirque Du Freak, #9)",
"ratings_count": 18194,
"title": "Killers of the Dawn (Cirque Du Freak, #9)"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5683",
"_score": 1,
"_source": {
"authors": "Laura Joffe Numeroff, Felicia Bond",
"average_rating": 4.16,
"average_rating_rounded": 4,
"books_count": 13,
"id": 5683,
"image": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"image_medium": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"isbn": "60278684",
"language_code": "",
"original_publication_year": 2000,
"original_series": "",
"original_title": "If You Take a Mouse to the Movies",
"ratings_count": 17938,
"title": "If You Take a Mouse to the Movies"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5685",
"_score": 1,
"_source": {
"authors": "Orson Scott Card, James Cameron",
"average_rating": 4.06,
"average_rating_rounded": 4,
"books_count": 15,
"id": 5685,
"image": "https://images.gr-assets.com/books/1225165505l/40289.jpg",
"image_medium": "https://images.gr-assets.com/books/1225165505m/40289.jpg",
"isbn": "99690608",
"language_code": "eng",
"original_publication_year": 1989,
"original_series": "",
"original_title": "The Abyss",
"ratings_count": 16318,
"title": "The Abyss"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5687",
"_score": 1,
"_source": {
"authors": "Katarina Bivald, Alice Menzies",
"average_rating": 3.56,
"average_rating_rounded": 4,
"books_count": 63,
"id": 5687,
"image": "https://images.gr-assets.com/books/1452107441l/25573977.jpg",
"image_medium": "https://images.gr-assets.com/books/1452107441m/25573977.jpg",
"isbn": "149262344X",
"language_code": "eng",
"original_publication_year": 2013,
"original_series": "",
"original_title": "Läsarna i Broken Wheel rekommenderar",
"ratings_count": 14571,
"title": "The Readers of Broken Wheel Recommend"
}
}
]
}
}
The value received as _scroll_id can be passed to the scroll API to fetch the next set of results and so on till the number of hits is zero.
Note
If your cluster has a lot of data, its not a good idea to run this logic to fetch all the results every time the query changes. You can add a condition to limit the number of results fetched or store the current query in state and only fetch all the results when required.
Here's an example on how you can implement this with ReactiveList. In the example I'm fetching the results each time the query changes but you can modify it to fetch results conditionally instead:
In your render function:
<ReactiveList
...
size={10}
onQueryChange={this.handleQueryChange}
/>
Here's how the handleQueryChange function can look like. This will give you all the results for the current query:
handleQueryChange = async (prev, next) => {
// avoid fetching the results for match_all query since dataset is large
if (next && !next.query.match_all) {
console.log('Fetching all results for query:', next);
// modify the query size here if needed (currently it is 10)
// initial url to obtain scroll id is different
const initialResults = await this.fetchResults(next, url);
// keep scrolling till hits are present
// NOTE: careful if you've a lot of results,
// in that case you might want to add a condition to limit calls to scroll API
const scrollResults = await this.fetchScrollResults({
scroll: "1m",
scroll_id: initialResults._scroll_id
});
// combine the two to get all results
// concat hits from initialResults with hits from scrollResults
const allResults = initialResults.hits.hits.concat(scrollResults);
console.log(`${allResults.length} results found:`, allResults);
}
};
Its using two functions for fetching the results initially and later with the scroll_id. The endpoints for both are different, which you can find in the demo. Here's how the first fetchResults looks like:
fetchResults = (query, api) => {
return fetch(api, {
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Basic ${btoa(credentials)}`
},
body: JSON.stringify(query)
})
.then(res => res.json())
.catch(err => console.error(err));
};
The fetchScrollResults will use the scroll API to fetch results till the hits obtained are 0.
fetchScrollResults = async query => {
const res = await this.fetchResults(query, scrollUrl);
const { hits } = res.hits;
if (hits.length) {
return [
...hits,
...(await this.fetchScrollResults({
scroll: "1m",
scroll_id: res._scroll_id
}))
];
}
return [];
};
Check the demo, results will appear in the console.
You are missing a key that identify unique components and you also need to wrap element inside function. If function is called properly and your array have elements this should work.
onAllData(shops) {
let result = null;
if (shops !== null) {
console.log(shops.length);
result = shops.map((marker,index) => { return (
<ListItem key={index}>
<Thumbnail square size={80} source={{ uri: 'https://dummyimage.com/80x80/000/fff' }} />
<Body>
<Text>{marker.name}</Text>
<Text note>{marker.dis}</Text>
</Body>
</ListItem>
)})
return result;
}

React.map defined but says undefined

UPDATE:
by the way I'm already defined the data with the response in
setState({ fetchedData: responseJSON.data })
I’m just getting the response data in setState called fetchedData: [] I’m wondering why I’m getting an error while I’m fetching movies from this.state.fetchedData even though if I did console log for this.state.fetchedData I’m getting this data
{
"data":{
"title": "The Basics - Networking",
"description": "Your app fetched this from a remote endpoint!",
"movies": [
{ "id": "1", "movieTitle": "Star Wars", …},
{ "id": "2", "movieTitle": "Back to the Future", …}
{ "id": "3", "movieTitle": "The Matrix", …}
{ "id": "4", "movieTitle": "Inception", …},
{ "id": "5", "movieTitle": "Interstellar", …}
]
}
}
Also if I did console log for this.state.fetchedData.movies I’m getting response
[
{ "id": "1", "movieTitle": "Star Wars", …},
{ "id": "2", "movieTitle": "Back to the Future", …}
{ "id": "3", "movieTitle": "The Matrix", …}
{ "id": "4", "movieTitle": "Inception", …},
{ "id": "5", "movieTitle": "Interstellar", …}
]
I have tried to use map it doesn’t work here’s my code
const allNews = this.state.fetchedData.movies.map((data) =>
<ul>
<li key={data.id}>{data.total}</li>
</ul>
);
I’m getting error says Cannot read property 'map' of undefined
Then I did a big research I got I should use object.key here’s my code:
const getData = this.state.fetchedData.map((items, index) => {
return (
<ul key={index}>
{Object.keys(items.movies).map((movie) => {
return (
<li key={movie.id}>{key.movieTitle}</li>
)
})}
</ul>
)
});
I’m getting error says
this.state.fetchedData.map is not a function
I really don’t know where’s my problem even though if I console log the Data I’m getting correct response
Thank you guys for helping me
You are not traversing through your state correctly, this will solve your problem.
const allNews = this.state.fetchedData.data.movies.map((data) =>
<ul>
<li key={data.id}>{data.total}</li>
</ul>
);
How is it that when printing this.state.fetchedData.movies you get { movies: [ ... ] }? Going by the shape of this.state.fetchedData you should only get the array in movies, but are getting an object that has a movies key inside.
Have you tried this.state.fetchedData.movies.movies.map?
How is it that this.state.fetchedData.movies isn't only the movies array? If it's an object no surprise you can't call map on it.
When are you calling setState({ fetchedData: responseJSON.data })? When is this.state.fetchedData.movies.map called? How can you be sure the state is set with fetchedData in the initial render?

Categories