React Fetch Inside a function Map - javascript

I'm trying to make a request for each item captured in the MAP, but I would like to wait for the response before going to the other object within the MAP. At the moment my code is making all the requests at the same time, which ends up crashing the Backend.
function RequestComputers (Computers) {
Computers.map((e) => {
Details(e, data.region, data.apitoken).then(data => {
if(data)
setContent2((array) => [...array, data[0]])} ).catch(error => console.log(error))
})
}
const Details = async (Computer, region, token) => {
try {
const test = {'region': region, 'apitoken': token, 'product': '1', 'computer': Computer}
const response = await fetch('url', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(test)
}
)
const data = await response.json()
return data
} catch(error) {
console.log(error)
}
}
I need to wait for the fetch response and only then make another fetch request

You can use a simple for loop:
async function RequestComputers (Computers) {
for ( const computer of Computers ) {
try {
const data = await Details(computer, data.region, data.apitoken);
if ( data ) {
setContent2((array) => [...array, data[0]]);
}
} catch(error){
console.log(error);
}
}
}
Reference

I think you could use .forEach and await Details:
async function RequestComputers (Computers) {
Computer.forEach(async(computer) => {
try {
const data = await Details(computer, data.region, data.apitoken);
if ( data ) {
setContent2((array) => [...array, data[0]]);
}
} catch(error){
console.log(error);
}
})
}

Related

Why does the fetch request returns an undefined data in Nextjs?

This is the code in the api sections for my GET request:
export default async (req, res) => {
const { query: { className }, method } = req;
switch (method) {
case "GET":
try {
const classDetail = await Class.findOne({title: className});
if (!classDetail) {
return res.status(400).json({ success: false });
}
res.status(200).json({ success: true, data: classDetail });
} catch (error) {
res.status(400).json({ success: false });
console.log(error);
}
break;
default:
res.status(400).json({ success: false });
}
In my [className] page, I want to fetch the data from http://localhost:3000/api/admin/classes/${className} API. I console logged the response, but it returns undefined for some reason.
export async function getServerSideProps({ query: { className } }) {
const res = await fetch(`http://localhost:3000/api/admin/classes/${className}`)
.then(() => console.log(`first get request sent: `));
// const { data } = await res.json();
console.log(res)
return { props: { classDetail: 1 } };
}
But when I send the same get request from postman using http://localhost:3000/api/admin/classes/class-3 API, it sends me the following data. I'm not getting the data from getServerSideProps.
{
"success": true,
"data": {
"_id": "62f6858ea26fbb47b3cc0563",
"title": "class-3",
"classImageURL": "http://res.cloudinary.com/nhnasem/image/upload/v1660323222/HELP_ME_ewcr5t.png",
"imageWidth": "1555",
"imageHeight": "2000",
"__v": 0
}
}
Why is this happening? And how can I resolve the issue?
Edit: I tried it with jsonplaceholder API. The result is the same undefined.
Edited 2: For two APIs
export async function getServerSideProps({ query: { className } }) {
const res = await fetch(
`http://localhost:3000/api/admin/classes/${className}`
);
const {data} = res.json()
const res2 = await fetch(
`http://localhost:3000/api/admin/classes/${className}/subjects`
);
const {data} = await res2.json() // it won't do, because it was called
// and initialized before
return { props: { classDetail: data, subjects: data} }; // ???????????
}
The reason is that extra .then() that you added to your fetch call.
When you add .then() to a promise chain, it receives the result of fetch as its argument and is supposed to return whatever should be the result of a promise. In your case, you're not returning anything, hence the undefined you get in your res variable. Instead, you should return the original result:
const res = await fetch(`http://localhost:3000/api/admin/classes/${className}`)
.then((res) => { console.log(`first get request sent: `); return res; });
or simply remove
.then(() => console.log(`first get request sent: `));
UPDATE
If both requests return an object with data property, you can't simply destructure both results due to duplicated variable name:
const {data} = await res.json()
const {data} = await res2.json();
What you can do, is to provide the name of a variable where data should be assigned:
const {data: classDetail} = await res.json()
const {data: subjects} = await res2.json();
return { props: { classDetail, subjects} };
or even be more explicit:
const json = await res.json()
const json2 = await res2.json();
return { props: { classDetail: json.data, subjects: json2.data} };

Handling query in React and Express

Somewhere in my React application I used REST API to send request to the server. In my URL I want to use query (in the postIconsTransition method), but when I send a request to the server, server tells me could not found this URL (I build this error in my server). If I use this URL without any query the request in the postIconsTransition method works fine. postId and authContext.userId work fine, can anyone tell me what's wrong with my code?
In my component where I send request:
const likeHandler = async () => {
setLike(prevState => !prevState);
if (!like) {
try {
await postIconsTransition(props.postId, "inc");
} catch (error) {}
} else {
try {
await postIconsTransition(props.postId, "dec");
} catch (error) {}
}
};
In useHttp.js component:
const postIconsTransition = async (postId, addtionAddress) => {
return await transitionData(
`http://localhost:5000/post/${postId}/${authContext.userId}?t=${addtionAddress}`,
"POST",
null,
{ Authorization: `Bearer ${authContext.token}` }
);
};
transitionData method:
const transitionData = useCallback(
async (url, method = "GET", body = null, headers = {}) => {
setIsLoading(true);
const abortController = new AbortController();
activeHttpRequest.current.push(abortController);
try {
const response = await fetch(url, {
method,
body,
headers,
signal: abortController.signal
});
const responseData = await response.json();
activeHttpRequest.current = activeHttpRequest.current.filter(
reqCtrl => reqCtrl !== abortController
);
if (!response.ok) {
throw new Error(responseData.message);
}
setIsLoading(false);
return responseData;
} catch (error) {
modalContext.err(error);
setIsLoading(false);
throw error;
}
},
[modalContext.err]
);
In Express:
router.post(
"/:postId/:userId?t=inc",
tokenChecker,
postController.updateLikesComments
);
router.post(
"/:postId/:userId?t=dec",
tokenChecker,
postController.updateLikesComments
);
All of them work fine but when I use query in my URL, it's not working any more.
You don't specify query parameters in express routes like that. Just send them. Express can read it.
router.post(
"/:postId/:userId",
tokenChecker,
postController.updateLikesComments
);
// Notice that you don't need the other one.
and in your controller check the parameter
// controller's code
const t = req.query.t;
if (t === 'inc') {
// do what you want here
}
if (t === 'dec') {
// do what you want here
}

Service call is not going in react-native. Getting warning like "Possible unhandled Promise Rejection, Reference error: response is not defined"

I am new to react native and making service call for the first time. My problem is service call is not going and getting warning like
Possible unhandled Promise Rejection, Reference error: response is not defined.
I am trying to hit loginUser function.
Api.js
const BASE_URL = "http://localhost:8200";
export const api = async (url, method, body = null, headers = {}) => {
try {
const endPoint = BASE_URL.concat(url);
const reqBody = body ? JSON.stringify(body) : null;
const fetchParams = {method, headers};
if((method === "POST" || method === "PUT") && !reqBody) {
throw new Error("Request body required");
}
if(reqBody) {
console.log("ReQBody--->"+reqBody);
fetchParams.headers["Content-type"] = "application/json";
fetchParams.body = reqBody;
}
const fetchPromise = await fetch(endPoint, fetchParams);
const timeOutPromise = new Promise((resolve, reject) => {
setTimeout(() => {
reject("Request Timeout");
}, 3000);
});
const response = await Promise.race([fetchPromise, timeOutPromise]);
return response;
} catch (e) {
return e;
}
}
export const fetchApi = async (url, method, body, statusCode, token = null, loader = false) => {
console.log("In FetchAPi Function");
try {
const headers = {}
const result = {
token: null,
success: false,
responseBody: null
};
if(token) {
headers["securityKey"] = token;
}
const response = await api(url, method, body, headers);
console.log("fetchApi-->>"+response);
if(response.status === statusCode) {
result.success = true;
let responseBody;
const responseText = await response.text();
try {
responseBody = JSON.parse(responseText);
} catch (e) {
responseBody = responseText;
}
result.responseBody = responseBody;
return result;
}
let errorBody;
const errorText = await response.text();
try {
errorBody = JSON.parse(errorText);
} catch (e) {
errorBody = errorText;
}
result.responseBody = errorBody;
console.log("FetchApi(Result)--->>"+result);
throw result;
} catch (error) {
return error;
}
}
auth.actions.js
export const loginUser = (payload) => {
console.log("In LoginUser function2");
return async (dispatch) => {
<-----**I am not able to enter into this block**------>
try {
dispatch({
type: "LOGIN_USER_LOADING"
});
console.log("In LoginUser function3");
const response = await fetchApi("/login", "POST", payload, 200);
if(response.success) {
dispatch({
type: "LOGIN_USER_SUCCESS",
});
dispatch({
type: "AUTH_USER_SUCCESS",
token: response.token
});
dispatch({
type: "GET_USER_SUCCESS",
payload: response.responseBody
});
return response;
} else {
throw response;
}
} catch (error) {
dispatch({
type: "LOGIN_USER_FAIL",
payload: error.responseBody
});
return error;
}
}
}
In console log, I can't see anything in network tab. In the android emulator, the mentioned warning has come.
My console tab
I see that your BASE_URL is served using an http endpoint. You can only make requests to https endpoints from react native projects. A possible workaround is to use ngrok. Just download it and run ./ngrok http 8200 since your port number is 8200. It will expose an HTTPS endpoint and replace your BASE_URL with that link and try fetching the data again.
I use the following code to make API calls. See if you can integrate it in your code. it is quite simple:
In a class called FetchService:
class FetchService {
adminAuth(cb, data) {
console.log('here in the fetch service');
return fetch(
baseURL + "login",
{
method: "POST",
headers: {
Accept: "application/json",
},
body: data
}
)
.then((response) => response.json())
.then(responsej => {
cb(null, responsej);
})
.catch(error => {
cb(error, null);
});
}
}
export default FetchService;
Then call it from your component using:
import FetchService from './FetchService';
const fetcher = new FetchService;
export default class LoginScreen extends React.Component {
fetchData() {
const data = new FormData();
data.append('username',this.state.username);
data.append('password',this.state.password);
fetcher.wastereport((err, responsej) => {
if(err) {
//handle error here
} else {
//handle response here
}
}, data);
}
}

How I can send my axios response to a variable with node.js

In fact, I begin with node.js. And i don't know how to pass the response to a variable. I don't want to make my code in my "response".. I try a lot of things but nothing is working.. I know is a simple question.. but it's not working
const axios = require('axios');
var test = null
function getLeagues () {
axios.get('https://api-football-v1.p.rapidapi.com/v2/fixtures/league/525?timezone=Europe/Paris', {
headers: {
'X-RapidAPI-Key': '<my-api-key>'
}
})
.then(response => {
test = response.data.api.fixtures
return response.data.api.fixtures
})
.catch(error => {
console.log(error);
});
}
console.log(test)
You should use promises and wait for the response to be ready:
const axios = require('axios');
function getLeagues () {
return axios.get('https://api-football-v1.p.rapidapi.com/v2/fixtures/league/525?timezone=Europe/Paris', {
headers: {
'X-RapidAPI-Key': 'foo-api-key'
}
})
.then(response => {
return response.data.api.fixtures
})
.catch(error => {
console.log(error);
return Promise.reject(error);
});
}
getLeagues().then(response => {
console.log(response);
});
Or, using async/await:
const consoleLeagues = async () => {
const leagues = await getLeagues();
console.log(leagues);
};
consoleLeagues();

return undefined fetch inside AsyncStorage

I have a react-native app where I do a call to an api where it should return the JSON but I'm just having undefined.
export function fetchFromAPI() {
AsyncStorage.getItem('#token', (errToken, token) => {
let token = null;
const requestBody = { token: token };
return fetch(url, {
method: 'POST',
body: JSON.stringify(requestBody)
})
.then((response) => response.json())
.then((responseJSON) => {
console.log(responseJSON); // <-- this shows the correct JSON data
return responseJSON;
}).catch((error) => {
// console.error(error);
});
});
}
I also call that funcion like this:
const apiData = fetchFromAPI();
If I do console.log() inside the fetch function, it returns the JSON data but if I do to apiData, it just gets undefined.
Does anyone has some idea why its like this, I'm doing something wrong?
You can use Promise to get response from fetchFromAPI function, like
export function fetchFromAPI() {
return new Promise((resolve, reject) => {
AsyncStorage.getItem('#token', (errToken, token) => {
let token = null;
const requestBody = {
token: token
};
return fetch(url, {
method: 'POST',
body: JSON.stringify(requestBody)
})
.then((response) => response.json())
.then((responseJSON) => {
console.log(responseJSON); // <-- this shows the correct JSON data
resolve(responseJSON);
}).catch((error) => {
reject(error);
});
});
});
}
When calling the fetchFromAPI, use await, like
const apiData = await fetchFromAPI();
You can also use .then to capture the response and store it in the state, like
fetchFromAPI.then((data) => {
// use data here
});
Hope this will help!
First, you need to return the Promise created by getItem:
export function fetchFromAPI() {
return AsyncStorage.getItem('#token', (errToken, token) => {
let token = null;
const requestBody = { token: token };
return fetch(url, {
method: 'POST',
body: JSON.stringify(requestBody)
})
.then((response) => response.json())
.then((responseJSON) => {
console.log(responseJSON); // <-- this shows the correct JSON data
return Promise.resolve(responseJSON); // <-- this wraps the JSON into a Promise
}).catch((error) => {
// console.error(error);
});
});
}
Then you need to call the function like this:
fetchFromAPI().then(apiData => {...

Categories

Resources