I'm trying to create a function for POST request in React app (due to I need it in few places), it should return a responseText in the useEffect statement. the variant I've googled doesn't act as async - the string console.log("JSON", json) put into the console JSON undefined before the getting response from server...
useEffect(() => {
(async function() {
try {
const response = await post_return(postData);
const json = await JSON.stringify(response);
console.log("json", json);
} catch (e) {
console.error(e);
}
})();
}, [postData]);
const API_URL_REGISTRATION = "https:.....";
export function post_return (dataPost) {
var xhr = new XMLHttpRequest();
xhr.open("POST", API_URL_REGISTRATION, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log("xhr.status", this.status);
console.log("this.responseText", this.responseText);
return xhr.status
}
};
xhr.onload = function () {
console.log("xhr.status", this.status);
console.log("this.responseText", this.responseText);
return xhr.status;
};
xhr.onerror = function () {
alert('Error' + this.status);
};
xhr.send(JSON.stringify(dataPost));
}
tried also:
export async function post_return (dataPost) {...
and:
xhr.onreadystatechange = async function ()
What I do wrong?
Thanks,
First thing that is wrong with post_return function is it returns undefined immediately, hence the response variable value is actually undefined and a result of calling JSON.stringify with undefined is also undefined. What you should do is to correct post_return so that it returns a Promise.
Simplest solution would be to use built-in fetch like so:
export function async post_return (dataPost) {
const response = await fetch(API_URL_REGISTRATION, {
method: 'POST',
body: JSON.stringify(dataPost),
headers: {
'Content-type': 'application/x-www-form-urlencoded'
}
});
if (response.ok) {
return response.json();
}
// Here you can do some basic error parsing/handling
throw new Error();
}
Rafal2228, thanks for your post, I adopted it for my needs
export async function post_return(url, dataPost) {
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(dataPost),
headers: {
'Content-type': 'application/x-www-form-urlencoded'
}
});
const json = await response.json();
return {
status: response.status,
body: json
};
}
useEffect(() => {
(async function() {
try {
if (postData.email !== undefined)
{
const response = await post_return(API_URL_REGISTRATION, postData);
// console.log("response", response);
setshowLoader(false);
if (response.status === 200) {
navigate("/login")
} else alert(response.body);
}
} catch (e) {
console.error('Ошибка ' , e);
}
})();
}, [postData]);
Related
I have a use effect with the helper function registerAccountInConfigurator(token)
acquireTokenForScope([`${process.env.REACT_APP_SW_SCOPE}`]).then(
(token) => {
if (token) {
// console.log(registerAccountInConfigurator(token));
registerAccountInConfigurator(token).then(function (response) {
console.log("response arrived ", response);
});
}
return null;
}
);
In case of an error in the helper function I want to do some steps and then call the function again.
export async function registerAccountInConfigurator(
adb2cToken: string,
change: any = false,
account?: any
) {
try {
const contextRes = await axios.get(
`${process.env.REACT_APP_SW_BASE_URL}/context`,
{
headers: change
? {
"sw-access-key": process.env.REACT_APP_SW_ACCESS_KEY ?? "",
...(adb2cToken !== "" && {
Authorization: `Bearer ${adb2cToken}`,
}),
}
: {},
}
);
const context: any = { ...contextRes.data };
const response = await axios.post(
`${process.env.REACT_APP_SW_BASE_URL}/post-ecommerce/account/register`,
account ?? { storefrontUrl: window.origin },
{ headers: headers(context.token, adb2cToken) }
);
const newToken = response.headers["sw-context-token"];
localStorage.setItem(SW_CONTEXT_TOKEN, newToken);
return response.data;
// Promise.resolve(response.data);
// return new Promise((resolve, reject) => {
// return resolve(response.data);
// });
} catch (error) {
console.log(error);
// do some steps
await registerAccountInConfigurator(adb2cToken, true);
}
}
To artficially test it with an 401 Error I use the paramater change which is per default false and will be set to true in the catch block.
What I dont understand is when I call console.log("response arrived ", response); with setting change to true. I get a normal response, an object. When I set change to false, triggering the catch block, I get undefined as the response value in console.log("response arrived ", response); why is that happening? How can i change that?
Can someone please tell me why my Axios service function returns this:
The object looks fine in the service function.
Promise {<fulfilled>: {…}}
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Object
Here is the call:
useEffect(() => {
setData(playlistService.getPlaylists);
}, []);
console.log(data);
And the function:
const config = {
headers: {
'Content-Type': 'application/json',
},
withCredentials: true,
};
const getPlaylists = async () => {
try {
const res = await axios.get(`${API_SONGS_URL}/`, config);
console.log('RES ', res);
return res;
} catch (error) {
if (error.response) {
return error.response.data;
}
}
};
this could work
useEffect(() => {
const fetchPlayListAsync = async () => {
const response = await playlistService.getPlaylists();
setData(response)
}
fetchPlayListAsync()
}, []);
you can add appropriate checks of fetched data
network.services.js
axiosCall = (axiosURL) => {
// const axiosURL = "https://api.github.com/user"
axios.get(axiosURL, {
headers: {
'Authorization': `qwdvryjutmnevw`,
}
}).then((res) => {
console.log(res.data);
return res.data;
}).catch((error) => {
throw error.message;
// console.error(error);
// toast.error(error.message);
})
}
component.js
const getData = async () => {
const asyncExample = async () => {
const result = await networkServices.axiosCall("/api/v1/calendars");
const responseData = await result;
console.log(responseData);
return responseData;
}
const data = asyncExample()
data.then(function(result) {
console.log(result); // "Some User token"
})
}
Trying to get data from service to my component in const result, console form service is consoling data but component is always returning undefined instead of data from the service file. SetTimeout function is also not working in component.
You have many mistakes. I advise you to take a look at documentation about Promises
First one:
You don't return data in axiosCall
A way to return data:
axiosCall = (axiosURL) => new Promise((resolve, reject) => {
axios.get(axiosURL, {
headers: {
'Authorization': `yourTokenHere`,
}
}).then((res) => {
// return a response data
resolve(res.data);
}).catch((error) => {
// return only error message
reject(error.message);
})
})
to use axiosCall:
try {
// don't forgot to configure axios with base url
const data = await axiosCall('/api/v1/calendars');
// do something with your data
} catch (e) {
// do something with error message
console.log(e);
}
Second:
Your make mistakes when call async function
Look at this example:
const getData = () => {
networkServices
.axiosCall("/api/v1/calendars")
.then(function(result) {
// when promise resolve
console.log(result);
})
.catch(error => {
// when promise reject
console.log(error)
})
}
I can not get the right info on my API.
i tried this and nothing comes back
const res = () => {
axios.get('https://api.scripture.api.bible/v1/bibles', {
headers: {
'api-key': '5b5d4503884b7a2515e8cee8f4b00746',
},
})
}
Your code works fine, but you are not doing anything with the response. axios.get() returns a Promise, so you need to handle it using .then()
const res = () => {
axios.get("https://api.scripture.api.bible/v1/bibles", {
headers: {
"api-key": "5b5d4503884b7a2515e8cee8f4b00746"
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
};
res();
or make an async function and use async await.
const res = async () => {
try {
const response = await axios.get("https://api.scripture.api.bible/v1/bibles", {
headers: {
"api-key": "5b5d4503884b7a2515e8cee8f4b00746"
}
});
console.log(response);
} catch (error) {
console.log(error);
}
};
res();
Instead of console.logging you can do anything, for example use a callback function:
const res = async (callback, errorCallback) => {
try {
const response = await axios.get("https://api.scripture.api.bible/v1/bibles", {
headers: {
"api-key": "5b5d4503884b7a2515e8cee8f4b00746"
}
});
callback(response);
} catch (error) {
errorCallback(error);
}
};
const onSuccess = result => {
const data = JSON.stringify(result);
alert(data)
};
const onError = error => {
alert(`Ops! An error occured: ${error}`);
};
res(onSuccess, onError);
I have a function api inside the method onSubmit, which make request to the server:
onSubmit: async (formValues) => {
setSubmitting(true);
try {
const res = await api('api/auth/register', {
method:'POST',
body: JSON.stringify(formValues)
});
if(Array.isArray(res)){
setErrorMessage(res[0].message);
} else {
const token = res.token.token;
localStorage.setItem('myToken', token);
history.push("/home");
}
} catch(e) {
console.error(e);
} finally {
setSubmitting(false);
}
},
});
Function api is in a separate file and looks like this:
export const api = async (url, args) => {
const response = await fetch(`${apiUrl}${url}`, {
...args,
headers: {
"Content-type": "application/json; charset=UTF-8 ",
"Accept": 'application/json',
...args.headers,
},
});
return response.json();
}
This function was created simply for convenience. But now I dont need this function. I need that code from api was inside method onSubmit. That is, that the function api not exist at all.
And I did it:
onSubmit: async (formValues) => {
setSubmitting(true);
try {
const resf = await fetch(`${apiUrl}api/auth/register`, {
method:'POST',
body: JSON.stringify(formValues),
headers: {
"Content-type": "application/json; charset=UTF-8 ",
"Accept": 'application/json',
}
});
const res = resf.json();
if (Array.isArray(res)){
setErrorMessage(res[0].message);
} else {
const token = res.token.token;
localStorage.setItem('myToken', token);
history.push("/home");
}
} catch(e) {
console.error(e);
} finally {
setSubmitting(false);
}
},
});
But I have error:
TypeError: Cannot read property 'token' of undefined
Why is this error occurring?
Try with await for resf.json() because calling .json() gets you another promise for the body of the http response that is yet to be loaded.
const res = await resf.json();