Get JSON data from axios request - javascript

I'm in react Native, and I have a request that im making using axios, and the request is supposed to return something like this:
Json data
I want to be able to save only the "Products" array in a variable.
This is the snippet of my cod, but it's giving me a 'Possible unhandled promise rejection' and I dont understand why:
const [shoesData, setShoesData] = useState([]);
useEffect(() => {
const getShoesData = async () => {
await axios.get("https://stockx.com/api/browse?productCategory=sneakers&sort=release_date&releaseTime=gte-" + Date.now().toLocaleString() + "&order=ASC&country=FR")
.then(response => {
let products = response.data.map(x => {
return x.products;
});
setShoesData(products);
console.log(products);
})
}
getShoesData();
}, [])
Thanks in advance for your help.

Try and wrap your await instruction with a try catch. One possible error can be that the data you get from the response can, in some cases, not have a products field.

Related

Cannot render and map POST request array promise

I have an API called getQuote and a component called QuoteCard. Inside QuoteCard I'm trying to render an array of users that liked a quote. The API works fine, I have tested it, and the code below for getting the users works fine too.
const Post = async (url, body) => {
let res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"accept": "*/*"
},
body: JSON.stringify(body)
}).then(r => r.json());
return res;
}
const getAllLikes = async () => {
let users = await Post('api/getQuote', {
id: "639e3aff914d4c4f65418a1b"
})
return users
}
console.log(getAllLikes())
The result is working as expected :
However, when trying to map this promise result array to render it onto the page is where I have problems. I try to render like this:
<div>
{getAllLikes().map((user) => (
<p>{user}</p>
))}
</div>
However, I get an error that states:
getAllLikes(...).map is not a function
I don't understand why this is happening. Why can't I map the array? Is it because it's a promise or something?
And if anyone needs to see the getQuote API, here it is:
//Look ma I wrote an API by myself! :D
import clientPromise from "../../lib/mongodb";
const ObjectId = require('mongodb').ObjectId;
import nc from "next-connect";
const app = nc()
app.post(async function getQuote(req, res) {
const client = await clientPromise;
const db = client.db("the-quotes-place");
try {
let quote = await db.collection('quotes').findOne({
_id: new ObjectId(req.body.id)
})
res.status(200).json(JSON.parse(JSON.stringify(quote.likes.by)));
} catch (e) {
res.status(500).json({
message: "Error getting quote",
success: false
})
console.error(e);
}
})
export default app
Thanks for any help!
It is due to the fact that getAllLikes is an async function and thus it returns promise which does not have a map function.
You can either save it in a state variable before using await Or chain it with .then.
Minimal reproducible example which works
const getAllLikes = async () => {
return ['a', 'b']
}
getAllLikes().then((r) => r.map((g) => { console.log(g) }))
Edit: The above code won't work if directly used with jsx since the return of getAllLikes will still be a promise. Solution would be to save it in a state variable and then using it.
I am from Angular and I believe we call pipe on Observables (or Promises). Map can then be called inside the pipe function
observable$ = getAllLikes().pipe(map( user => <p>{user}</p>))
If there is no pipe, I can only think of manually subscribing (which is not a good practice)
sub$ = getAllLikes().subscribe( user => <p>{user}</p>)
// unsub from sub$ appropriately
// We do this from ngOnDestroy in angular
ngOnDestroy() {
this.sub$?.unsubscribe()
}

Using Fetch to Return GitHub User Data

Forgive the ignorance, I'm not great with JavaScript (yet). I'm trying to fetch public user data from GitHub and display it on my personal portfolio. Currently I have the code below:
getData(url) {
return fetch(url);
}
const userData = getData("https://api.github.com/users/userName");
userData
.then((response) => response.json())
.then((response) => console.log(response))
.catch((error) =>
console.log("There was an error fetching the data: " + error)
);
console.log(userData)
The response I get is the JSON with the user data but when I console.log(userData) I get Promise { <state>: "pending" } as the response.
Also, I can see that there is an id in the initial response but when I console.log(userData.id) I get undefined.
I've read the GitHub API docs and watched a few videos on Promises but I can't seem to get my code to work correctly.
Thanks for taking the time to look at this and any help with this is greatly appreciated!
It is because userData is a promise. If you try using async/await (documentation is available here) you'll be able to synchronously get the data.
const getData = async (url) => {
try {
const data = await fetch("https://api.github.com/users/:user_name");
console.log(data.json());
return data;
} catch (e) {
console.log("There was an error fetching the data: " + error)
}
}

Extracting array elements from JSON (javascript)

I'm trying to manipulate JSON data received from an API url (this is my first time handling this type of work)
The following function returns a promise of a 20 element array:
const articles = () => {
return fetch(url)
.then(res => res.json())
.then(post => post.articles);
};
Console view:
Now, I'd like to extract the elements from the array - I tried something like:
articles()[0].name
but this doesn't work and I'm not sure of an alternative way to go about this? Appreciate your help. Thanks
Your articles fucntion returns a promise. You have to consume the promise (more on MDN):
articles().then(articleArray => {
console.log(articleArray);
});
or within an async function:
const articleArray = await articles();
console.log(articleArray);
Side note: Your fetch code is missing a check for HTTP success (HTTP failure isn't a rejection). You're by far not the only person who misses out this check, so much so that I've written a post on my anemic blog about it. With the check:
const articles = () => {
return fetch(url)
.then(res => {
if (!res.ok) {
throw new Error("HTTP error " + res.status);
}
return res.json();
})
.then(post => post.articles);
};

Cannot console.log fetch results

I'm trying to do an API call using fetch().
I'm aware that fetch() returns a Promise and should be handled using .then or await. The same for the result.json() Followed this tutorial http://www.reactnativeexpress.com/networking, I arrived with fetchRoute()function. The console.log(route) inside the function is never called.
I tried to return console.log(fetchRoute(this.state.userLocation, text)), but it was still returning a Promise.
I read another quesiton here on Stack Overflow (sorry, can't find the link anymore), and they said to try something like this:
getRouteHandler = (text) => {
fetchRoute(this.state.userLocation, text).then(json => console.log(json));
Still, I couldn't log the fetch results. Anyone knows what could be going wrong? Here is the relevant code:
const fetchRoute = async (ori, dest) => {
let origin = ori.latitude+','+ori.longitude;
let destination = encodeURIComponent(dest);
const key = "MyAPIKey";
const URL = `https://maps.googleapis.com/maps/api/directions/json?origin=${origin}&destination=${destination}&key=${key}`;
try{
const response = await fetch(URL)
const route = await response.json()
console.log(route)
return route
}catch(e){
return e
}
}
export default class App extends Component{
state = {
userLocation: null,
route: [],
}
getRouteHandler = (text) => {
fetchRoute(this.state.userLocation, text).then(json => console.log(json));
}
Sometimes if you're fetching large amounts of data it will take awhile for it to log. For example, in a past project the api I was fetching from had close to 5 million records. It took a few minutes to see anything in the console.

Angular 4.0 http put request

I've written a function to send a http put request to update some data but it says, that it is not recieving any data:
updateHuman(human: Human) {
const url = `${this.url}/${human.id}`;
const data = JSON.stringify(human);
return this.http.put(url, data).map(
response => response.json().data as Human,
error => console.log(error)
);
}
After I've changed my function to the following, it is working:
updateHuman(human: Human) {
const url = `${this.url}/${human.id}`;
const data = JSON.stringify(human);
return this.http.put(url, data).map(() => human);
}
Could someone explain me, why the first function is not working but second is working?
Observables are lazy, you need to be subscribed to them for them to work and retrieve anything. Did you subscribe to your method? Example:
methodToUpdateHuman(human): void{
...
this.updateHuman(human).subscribe((response) => {
//do something with the response
console.log.("Response is: ", response);
},
(error) => {
//catch the error
console.error("An error occurred, ", error);
});
}
I suggest you read through the Angular Tour Of Heroses, it's based in angular 2 and most of the functionality is functional in angular 4, there is a section dedicated to http requests: https://angular.io/tutorial/toh-pt6
In the second example you are not returning the response within the map, you are returning the human that was originally passed in.
So, basically you are creating an illusion that it is working, when it isn't.
Probably best to test your API with something like PostMan, to see if you can get it working with that first.
You use map method incorrectly, read more about this method in documentation: http://xgrommx.github.io/rx-book/content/observable/observable_instance_methods/map.html
If you want receive response from server your code should look like that:
updateHuman(human: Human) {
const url = `${this.url}/${human.id}`;
const data = JSON.stringify(human);
return this.http.put(url, data).subscribe(
response => response.json().data as Human,
error => console.log(error)
);
}
You can use map method if you want to modify server response(map some objects to other structures etc.):
updateHuman(human: Human) {
const url = `${this.url}/${human.id}`;
const data = JSON.stringify(human);
return this.http.put(url, data)
.map(response => { return response.json() }) // you can get json response here
.subscribe(
response => response.data as Human, // -- change here --
error => console.log(error)
);
}
map method returns Observable object, so you can subscribe that and wait for response, error or simple complete method(third parameter of subscribe()):
http://xgrommx.github.io/rx-book/content/observable/observable_instance_methods/subscribe.html

Categories