Data from an api depend on another api - reactjs

Hi i wanna make an api call which depends another API. One API give me the ID from a random movie, and the second give me the details about that movie. All is separated in a file api.js and exported to a component. If i export the function i get a Promise how is fullfilled but not the movie details. How can i resolve this nested API? Here is the code if its help
export async function getMovieDetail() {
const data = await fetch(`https://api.themoviedb.org/3/trending/all/day?
api_key=${apiKey}`).then((res) => res.json());
const movie = data.results[random].id;
async function getMovieById() {
const data = await fetch(`https://api.themoviedb.org/3/movie/${movie}?
api_key=${apiKey}&language=en-US`).then((res) => res.json());
return data;
}
const movieDetail = await getMovieById();
return movieDetail;
}

chain both requests like this
export async function getMovieDetail() {
return fetch(`https://api.themoviedb.org/3/trending/all/day?
api_key=${apiKey}`)
.then((res) => res.json())
.then((data) => {
const movie = data.results[random].id;
return fetch(`https://api.themoviedb.org/3/movie/${movie}?
api_key=${apiKey}&language=en-US`)
}).then((res) => res.json());
}

Related

What is the proper way to make api calls and get the author information of each post by id?

I'm building a blog app and I want to list all the posts stored in MongoDB. Each post object has an author id, and I want to get the posts and then get the author name of each post and add it as an attribute to the post object.
I defined the methods getUserById and getPosts to make api calls to a Node.js backend, and they both work fine.
Now I'm doing something like this in the useEffect hook of the component, which does not work properly:
useEffect(() => {
const fetchPosts = async () => {
const res = await getPosts();
let posts = res.data;
posts.map(async (post) => {
const res = await getUserById(post.userId);
post.username = res.data.username;
});
setPosts(posts);
};
fetchPosts();
}, []);
I'm wondering what is the proper way to implement something like this. Thanks.
Let add async to effects function and await for fetchPosts():
useEffect(async () => {
const fetchPosts = async () => {
const res = await getPosts();
let posts = res.data;
posts.map(async (post) => {
const res = await getUserById(post.userId);
post.username = res.data.username;
});
setPosts(posts);
};
await fetchPosts();
}, []);

Axios Error Networ error on request Google place api

im trying to make a request to google api but returns me network error. If i put the url in the browser, brings me the information correctly.I tryed to formate the request without success. The google places search works correctly too.
export const fetch_information = (skip, limit, filter) => async (dispatch) => {
try {
var url = `https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJk0aJYPbk3JQRLpKN20Jecko&fields=name,rating,formatted_phone_number&key=MyKey`;
const {data} = await axios.get(url)
console.log(data)
} catch (error) {
console.log(error.message)
}
}
and
export const fetch_information = (skip, limit, filter) => async (dispatch) => {
try {
var url = `https://maps.googleapis.com/maps/api/place/details/json?`;
let config = {
params: {
place_id: 'ChIJk0aJYPbk3JQRLpKN20Jecko',
key: 'myKey',
},
}
const {data} = await axios.get(url, config)
console.log(data)
} catch (error) {
console.log(error.message)
}
}
I think that the request looks a bit messy. I'm under the impression that you are trying to pass results to a redux store. Let's see if we can clean this up a bit.
export const fetch_information = async () => dispatch => {
const req = await axios.get("https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJk0aJYPbk3JQRLpKN20Jecko&fields=name,rating,formatted_phone_number&key=MyKey");
const data = await req.json();
return data;
//or, for your purpose...
console.log(data);
//can also dispatch for store
}
I didn't see anything you were passing as necessary for this.

2 API Calls with Axios, both show up in local server - but only one appears deployed

I made 2 API calls in React with Axios. In my local server both calls appear, after being deployed to Netify, only the first API call appears. I don't know what is causing it bc I have no error messages.
Right image is after it's been deployed, and the left image is the one on the local server. I XXXed my key, so it doesn't appear in the code
import axios from 'axios';
const API_URL = 'https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=XXXX';
const API_URL2= 'http://newsapi.org/v2/top-headlines?sources=ars-technica&apiKey=XXXX';
export const getNews = async () => {
const result = await axios.get(API_URL)
.then(response => {
return response.data.articles;
});
return(result);
}
export const getNews2 = async () => {
const result = await axios.get(API_URL2)
.then(response => {
console.log(response.data)
return response.data.articles;
})
.catch(function (error) {
// handle error
console.log(error);
})
.finally(function () {
// always executed
});
return(result);
Why first is https and second http ?

Can't get response from ipify using fetch in React

In my React app, I want to get the IP address of the user at client side. I intended to use ipify for that. When I'm using 'http://api.ipify.org/?format=json' in the browser, it successfully returns {"ip":"112.135.11.128"}, but I can't get the same response when I'm making request through fetch API. What I get is something like below.
code:
import React, { useEffect } from 'react';
const QRDisplay = () => {
async function getIP(){
const response = await fetch('https://api.ipify.org/?format=json');
const data = await response.json();
return response.status === 200 ? data : "err"
}
useEffect( () => {
getIP().then(data => console.log(data))
},[])
return (
<>
</>
);
};
export default QRDisplay;
You need to call .json() method to get body.
async function getIP(){
const response = await fetch('http://api.ipify.org/?format=json');
const data = await response.json();
return data;
}
Then you can use it like so:
getIP().then(data => console.log(data);
Similar approach to Ozan Bulut
await fetch('http://api.ipify.org/?format=json')
.then(response => response.json())
.then(data => {
/* use data here */
});

Map over Axios Response and append 2nd Axios Response to 1st

I'm creating a movie search React App using axios and the TMDb API. I want to make an axios.get call to search for a movie based on query, then map over the response, and pass the movie.id for each movie into a 2nd axios call to get more details for each movie.
I have tried many approaches, but I'm confused about how I need to return the values, or if I need to use async/await at some point in the code to wait for responses. I don't really know the best way to go about this - there's got to be a simple way to do it in sequence, but the asynchronous nature of the problem makes this difficult for me.
I thought it would be simpler to make my first axios call inside my search function, and then write a second function getDetails(id) that takes a movie id and makes an axios call with it.
Ideally, if I call the getDetails function in a map, get a response, append that response to my movies array, I could easily have an array of movies with appended details to each individual movie. I could then store the entire array in state, and use a single piece of state to manage all my movie data. I know that this process is not synchronous and that axios is promise based, but is there a way to go about this sequentially or am I approaching it all wrong? I know that .push() is not working in this situation, but I have tried other methods and they have always returned undefined, a promise, or an unintended result.
const search = query => {
axios
.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
)
.then(response => {
response.data.results.map(movie => {
const details = getDetails(movie.id);
return movie.push(details);
});
});
};
const getDetails = id => {
axios
.get(
`https://api.themoviedb.org/3/movie/${id}?api_key=${API_KEY}&language=en-US`
)
.then(response => {
return response.data;
});
};
EDIT 1: I've played with the answer by Abanoub Istfanous, and it seemed to return undefined with the added dispatch to update my state. I tweaked it more and the second set of code marked WORKING seems to be displaying some search results, but I cannot render any of the appended data from getDetails to the screen, as they are showing undefined. Am I still doing something incorrectly?
NOT WORKING:
const search = async query => {
dispatch({
type: MOVIE_SEARCH_REQUEST
});
const response = await axios.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = Promise.all(
response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
})
);
dispatch({
type: MOVIE_SEARCH_COMPLETE,
payload: data
});
return data;
};
// getDetails is unchanged...
WORKING:
const search = async query => {
dispatch({
type: MOVIE_SEARCH_REQUEST
});
const response = await axios.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = Promise.all(
response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
})
);
dispatch({
type: MOVIE_SEARCH_COMPLETE,
payload: response.data.results
});
return data;
};
// getDetails is unchanged...
I recommend to use Promise
/*
*#return data
*/
const getDetails = async (id) => {
const response = await axios
.get(
`https://api.themoviedb.org/3/movie/${id}?api_key=${API_KEY}&language=en-US`
)
return response.data
};
then
const search = async (query) => {
const response = await axios
.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = Promise.all(response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
}))
return data
};
The reason why it returns undefined is because Promise.all() will be executed asynchronously on the job queue and will only return the result after all Javascript gets executed and the call stack gets empty. So a simple solution to your code will be placing an await before Promise.all().
const search = async query => {
dispatch({
type: MOVIE_SEARCH_REQUEST
});
const response = await axios.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = await Promise.all(
response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
})
);
dispatch({
type: MOVIE_SEARCH_COMPLETE,
payload: response.data.results
});
return data; //No need to return data since you are dispatching it to redux store
};
You can read more about the asynchronous nature of JS on browsers here:
https://medium.com/#Rahulx1/understanding-event-loop-call-stack-event-job-queue-in-javascript-63dcd2c71ecd

Resources