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 => {...
Related
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);
}
})
}
so the idea is everytime i click the button it will dispatch my action,and i want to push my response data into an array, but it always overwrite an exising array, how do i fix it?
this is my code
function searchApiPhoto(param, page) {
const config = {
headers: {
Authorization: 'api-token',
},
}
return axios
.get(apiurl, config)
.then((res) => {
let data = []
// let result = [];
// console.log("data :", res.data.results);
// data = [...res.data.results];
// data.push(...res.data.results);
data.push(res.data.results)
console.log('datas =>', data)
// return result;
return res.data.results
})
.catch((err) => {
console.log(err)
})
}
const displayCharacters = async () => {
if(filteredCharacters !== 'default'){
const a = filteredCharacters.map(e => e.name);
const options = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ 'data' : a })
};
const b = await fetch("/image",options).then(res => res.json())
return b;
}else{
return "yikes";
}
}
console.log(displayCharacters());
I have this fetch request but when I log the results this is what i see :
Promise {<resolved>: "yikes"}
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: "yikes"
I just want the promiseValue and not this whole thing around it. How do i do this?
the async function returns a promise instantly, without waiting for the promise to resolve. You may instead console.log inside the function:
const displayCharacters = async () => {
if(filteredCharacters !== 'default'){
const a = filteredCharacters.map(e => e.name);
const options = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ 'data' : a })
};
try {
const b = await fetch("/image",options).then(res => res.json());
console.log(b);
//the better practice is however, to do like:
const b = await fetch("/image",options)
const result = await b.json();
console.log(result );
}
catch(err) {
console.log(err);
}
}else{
console.log("yikes");
}
}
displayCharacters();
The best way that i know to use fetch goes something like this:
const displayCharacters = async () => {
if(filteredCharacters !== 'default'){
const a = filteredCharacters.map(e => e.name);
const options = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ 'data' : a })
};
const b = await fetch("/image",options)
.then(res => {
// Handle API Errors
if (!res.ok) {
throw Error(res.statusText);
}
// Return if no errors
return res.json();
})
// this is the data you want
.then(data => data)
// it will only reject on network failure or if anything prevented the request from completing
.catch(error => {
console.log(error.message)
});
return b;
}else{
return "yikes";
}
}
Basically you chain two thens and a catch to completely understand the response
- the first then checks for api level errors
- second then gets you the data
- catch is invoked in case when it is not able to reach the api itself like connection issues
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();
So I'm using React with React-Router.
I have a onEnter hook which checks if the user is authenticates yes/no and executes the desired action.
export function requireAuth(nextState, replaceState) {
if (!isAuthenticated()) {
if (!Storage.get('token')) replaceState(null, '/login');
return delegate().then(() => replaceState(null, nextState.location.pathname));
}
if (nextState.location.pathname !== nextState.location.pathname) {
return replaceState(null, nextState.location.pathname);
}
}
When the token is expired I call a delegate function which looks like:
export function delegate() {
const refreshToken = Storage.getJSON('token', 'refresh_token');
return getData(endpoint)
.then(res => {
Storage.set('token', JSON.stringify({
access_token: res.data.access_token,
refresh_token: refreshToken,
}));
});
}
The delegate function indeed refresh the tokens in the localStorage. But the requests after the replaceState are not using the updated token, but the previous one. I think this is a async issue, someone knows more about this?
Edit: The function where I use the token:
function callApi(method, endpoint, data) {
return new Promise((resolve, reject) => {
let headers = {
'Accept': 'application/json',
'X-API-Token': Storage.getJSON('token', 'access_token'),
};
const body = stringifyIfNeeded(data);
const options = { method, headers, body };
return fetch(endpoint, options)
.then(response =>
response.json().then(json => ({ json, response }))
).then(({ json, response }) => {
if (!response.ok) {
reject({ json, response });
}
resolve(json);
}).catch((error, response) => {
reject({ error, response });
});
});
}