I am new to react and I want to make an Axios.get() request based on a function parameter. This is what I tried.
const mentorName = (value) => {
try {
Axios.get(
`${BASE_URL}/api/v1/consultations/${value}`
).then(res => {
if (res.status !== 200 || res.data.status !== "success") {
console.log(res)
return
}
})
} catch (error) {
console.log(error)
}
}
But It didn't work as res was not printed in console. What is wrong in this?
The code that worked fine is:
const mentorName = (value) => {
try {
const res = Axios.get(
`${BASE_URL}/api/v1/consultations/${value}`
)
if (res.status !== 200 || res.data.status !== "success") {
console.log(res)
return
}
} catch (error) {
console.log(error)
}
}
The below code worked fine but returns information wrapped in a promise. How to access it now because res.data is not a valid property.
Can you try this with async/await.
import axios from 'axios';
const mentorName = async value => {
try {
const res = await axios.get(`${BASE_URL}/api/v1/consultations/${value}`);
console.log(res);
} catch (error) {
console.log(error);
}
};
In the console.log inside try block you can check for the api response.
const mentorName = (value) => {
try {
Axios.get(
`${BASE_URL}/api/v1/consultations/${value}`
).then(res => {
if (res.status !== 200 || res.data.status !== "success") {
console.log(res)
return
}
})
} catch (error) {
console.log(error)
}
}
above code doesn't print because of the if condition, it is likely that the status is going to be 200 most of the time and anything apart from 200 would drill down to catch block
the reason it is printing promise in below code is because, it is a promise waiting to be fulfilled and the comparison / condition you have put up is very much fine because res is a promise and res.status is undefined
const mentorName = (value) => {
try {
const res = Axios.get(
`${BASE_URL}/api/v1/consultations/${value}`
)
if (res.status !== 200 || res.data.status !== "success") {
console.log(res)
return
}
} catch (error) {
console.log(error)
}
}
tweak the code to include an else block and you can always see something printed in console
const mentorName = (value) => {
try {
Axios.get(
`${BASE_URL}/api/v1/consultations/${value}`
).then(res => {
if (res.status !== 200 || res.data.status !== "success") {
console.log(res)
return
} else {
console.log(res);
}
})
} catch (error) {
console.log(error)
}
}
I do not recommend using async/await due to one single and pressing reason, that the UI thread is put on hold until the async call is resolved. just to make it look like a synchronous call. stick on to the promise way.
Related
I have this interceptors that logs the user out if unauthorized. I do, however, get more than a 401 response, and the interceptors does therefore run for as many times as the responses I get (4). Is there a way to make it run only for the first one?
This is my code:
api.interceptors.response.use(
(response) => response,
(err) => {
if (err.response.status === 401 && isLoggedIn) {
api
.delete("auth/sign_out")
.then((resp) => {
clearLocalStorage();
})
.catch((err) => {
clearLocalStorage();
});
} else {
return Promise.reject(err);
}
return err;
}
);
You might want something like this to "lock out" the possible re-entrant calls:
let isLoggingOut = false; // global
// ...
api.interceptors.response.use(
(response) => response,
async (err) => {
if (err.response.status === 401 && isLoggedIn) {
if(!isLoggingOut) {
isLoggingOut = true; // disallow re-entrant calls
try {
await api.delete('auth/sign_out');
} catch (deletionError) {
// throw errors away
} finally {
clearLocalStorage();
isLoggingOut = false;
isLoggedIn = false; // if the variable is assignable
}
}
}
return err;
},
);
I'm learning react JS and this is the code of tutorial person's code where they used .then but I tried doing it with async await, and I'm getting slightly different result than the tutorial person, below is tut person's code
useEffect(() => {
fetch(url)
.then((resp) => {
if (resp.status >= 200 && resp.status <= 299) {
return resp.json();
} else {
setIsLoading(false);
setIsError(true);
throw new Error(resp.statusText);
}
})
.then((user) => {
const { login } = user;
setUser(login);
setIsLoading(false);
})
.catch((error) => console.log(error));
}, []);
my code:
const getusers = async () => {
const resp = await fetch(url);
if (resp.status >= 200 && resp.status <= 299) {
const user = await resp.json();
const { login } = user;
setuser(login);
setIsLoading(false);
} else {
setIsLoading(false);
setIsError(true);
throw new Error(resp.statusText);
}
};
try {
useEffect(() => {
await getusers();
}, []);
} catch (error) {
console.log("error");
}
This is the output. The tutorial person doesn't get the error screen at the end(it should only show error as text)
Looks like you need to define the promise within the useEffect hook like so:
useEffect(() => {
let didCancel = false;
const getUsers = async () => {
const resp = await fetch(url);
if (didCancel) { // Ignore if we started fetching something else
console.log(resp);
return;
}
if (resp.status >= 200 && resp.status <= 299) {
const user = await resp.json();
const { login } = user;
setuser(login);
setIsLoading(false);
} else {
setIsLoading(false);
setIsError(true);
throw new Error(resp.statusText);
}
};
getUsers();
return () => { didCancel = true; }; // Remember if we start fetching something else
}, []);
note: if your promise depends on any values, like a userId string or something, then it need to go into the dependency array at the end of the useEffect hook.
Here are some good reference that addresses this issue:
react-hooks-fetch-data
github issue on same topic
I got the problem it was with try catch I moved try catch to inside the getuser function. It works now.
const getusers = async () => {
const resp = await fetch(url);
if (resp.status >= 200 && resp.status <= 299) {
try{
const user = await resp.json();
const { login } = user;
setuser(login);
setIsLoading(false);
} else {
setIsLoading(false);
setIsError(true);
throw new Error(resp.statusText);
}}
catch(error){
console.log("error");
}
};
useEffect(() => {
getusers();
}
I post data to server using fetch:
fetch(url, {
method: 'post'
})
.then(status)
.then((data) => {
console.log(data);
}).catch((error) => {
console.log('error: ' + error);
});
});
This is status method
const status = (res) => {
console.log(res);
if(res.status >= 200 && res.status < 300) {
return Promise.resolve(res.json());
} else {
return Promise.reject(res.json());
}
}
If code is 200 then it works fine (I receive my JSON). But when it is not, I catch the error and log it. It shows Unauthorized but I expect that I receive my error JSON. Something like this
{
"status": 400,
"error": "pass is not corret"
}
How can I catch my Json error?
At this point I'd think that you'd just need to return the JSON from the response. Judging by your conditional though you're returning the JSON regardless?:
const status = (res) => {
console.log(res);
if (res.status >= 200 && res.status < 300) {
return res.json();
}
}
res.json() returns a Promise. When you call Promise.reject you can only pass it a reason for the rejection. Like a string, object or Error describing why you're rejecting.
I would change the code a bit to
const status = (res) => {
return new Promise((resolve, reject) => {
res.json().then((json) => {
if(res.status >= 200 && res.status < 300) {
resolve(json);
}
else {
reject(json)
}
});
});
}
Source:
MDN - Promise.resolve
MDN - Promise.reject
The first chunk as an action creator below works as is with thunk, but I want to also apply the 2nd chunk, which is a promise middleware. How do I tweak it so that it can dispatch 2 actions?
export const fetchPokemon = function (pokemonName) {
return function (dispatch) {
dispatch({type: 'REQUESTING'})
const requestURL = `http://pokeapi.co/api/v2/pokemon/${pokemonName}/`
return fetch(requestURL)
.then(function (response) {
return response.json()
})
.then(function (data) {
dispatch(receivePokemon(formatPokemonData(data)))
dispatch(fetchPokemonDescription(pokemonName))
})
}
}
middleware
const fetchPromiseMiddleware = store => next => action => {
if (typeof action.then !== 'function') {
return next(action)
}
return Promise.resolve(action).then(function (res) {
if (res.status >= 400) {
throw new Error("Bad response from server")
}
return res.json()
}).then(store.dispatch)
}
I've tried the below but get an error:
store.js:33 Uncaught (in promise) TypeError: (0 ,
_actionCreators.receivePokemon) is not a function
const fetchPromiseMiddleware = store => next => action => {
if (typeof action.then !== 'function') {
return next(action)
}
return Promise.resolve(action).then(function (res) {
if (res.status >= 400) {
throw new Error("Bad response from server")
}
return res.json()
}).then(function (data) {
return store.dispatch(receivePokemon(formatPokemonData(data)))
}).then(function (data) {
return store.dispatch(fetchPokemonDescription(data.name))
})
}
there's not enough code in your question, but it seems when you call receivePokemon(formatPokemonData(data)) in the code you show, receivePokemon isn't a function, now you need to check where is that defined, it probably isn't.
I am trying to find a nice way of handling http responses that I consider an error. I am using fetch in React Native. Here is my code.
loginRequest(url) {
return fetch(url, {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;'
},
....
})
.then(response => {
return this.processResponse(response);
});
}
Then...
processResponse(response) {
if (response.status === 200) {
return response.json();
} else {
let error = new Error(response.status);
error.response = response.json(); // This is the problem
error.status = response.status;
throw error;
}
},
And the above are called like this:
return ApiRequests.loginRequest(username, password)
.then(json => {
dispatch(Actions.loginSuccess(json, username, password));
})
.catch(error => {
dispatch(Actions.loginFailure(error));
});
};
The idea is that I can easily handle all the errors separately (we assume anything but 200 error), within the catch. The problem is that response.json() returns a promise, so assigning it to error.response is not working. I need to keep track of http status code and the response body.
How about this:
processResponse(response) {
if (response.status === 200) {
return response.json();
} else {
return response.json().then((data) => {
let error = new Error(response.status);
error.response = data;
error.status = response.status;
throw error;
});
}
}