How to make common API call function using fetch - reactjs

I am trying to make common function which will handle all of my API calls from anywhere
I am using react": "^16.8.6" and fetch for making api call
So far what i have figure out to do
is
Helper.js
export function ApiHelper(url, data = {}, method = 'POST') {
let bearer = 'Bearer ' + localStorage.getItem('user_token');
var promise = fetch(url, {
method: method,
withCredentials: true,
// credentials: 'include',
headers: {
'Authorization': bearer,
'X-FP-API-KEY': 'chaptoken',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(
(result) => {
console.log(result);
},
(error) => {
error = error;
}
)
}
export function AnyOtherHelper() {
return 'i am from helper function';
}
And here is from where i am calling this function
componentDidMount() {
let url = `http://localhost/project/api/getdata`;
let op = ApiHelper(url);
}
when I console result in then i am getting appropriate result but what i want to return that response how can i do this part is troubling me
Even i have try to store the result in global variable and it is not working.
Also i have to return the response only when promise is resolved.

You are making an async call from your helper function which means, you will have to return promise from your helper function like this -
export function ApiHelper(url, data = {}, method = 'POST') {
let bearer = 'Bearer ' + localStorage.getItem('user_token');
return fetch(url, { // Return promise
method: method,
withCredentials: true,
// credentials: 'include',
headers: {
'Authorization': bearer,
'X-FP-API-KEY': 'chaptoken',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then((result) => {
console.log(result);
return result;
}, (error) => {
error = error;
})
}
USAGE
componentDidMount() {
let url = `http://localhost/project/api/getdata`;
ApiHelper(url)
.then(resposnse => {
console.log(resposnse);
});
}

Related

Axios Interceptor is not working in React JS

I am using the below code as an interceptor in my React JS app for getting token back but unfortunately, it is not working. Refresh token returns new idToken and updates local storage data correctly. The same code I'm using some other application which works fine. One main difference is that I currently use React 18 and the previous 16. I struggled to identify the problem but failed. Your help will be appreciable.
axios.interceptors.response.use(
(response) => {
return response;
},
(error) => {
if (error.response.status === 401) {
// console.log(error.response.data.code)
let usersData = JSON.parse(localStorage.getItem("userData"));
const refreshToken = usersData.refreshToken;
return axios
.post(
`${api_base_url}/auth/authentication/refresh_token`,
JSON.stringify({
refresh_token: refreshToken,
})
)
.then((response) => {
usersData["accessToken"] = response.data.data.accessToken;
usersData["idToken"] = response.data.data.idToken;
setSessionStorage("userData", usersData);
error.response.config.headers[
"Authorization"
] = `Bearer ${response.data.data.idToken}`;
return axios(error.response.config);
})
.catch((error) => {
if (error.response.data.code !== "TOKEN_EXPIRED") {
return;
}
localStorage.clear();
window.location = "/login";
});
}
return Promise.reject(error);
}
);
function getIRequestProp(severType, isMultipart, isSocial) {
const serverUrl = severType ? social_api_base_url : api_base_url;
let userData = JSON.parse(localStorage.getItem('userData'));
let idToken;
idToken = userData !== null ? userData['idToken'] : '';
let content_type;
if (isSocial) {
content_type = 'application/x-www-form-urlencoded'
} else {
content_type = isMultipart ? 'multipart/form-data' : 'application/json'
}
return {
serverUrl: serverUrl,
requestHeader: {
'Content-Type': content_type,
'Accept-Language': DEFAULT_LANGUAGE,
Authorization: `Bearer ${idToken}`
}
};
}
async function post(url, body, isSocialServer, isMultipart) {
const {serverUrl, requestHeader} = getIRequestProp(isSocialServer, isMultipart);
return axios.post(serverUrl + url, body, {
headers: requestHeader
});
}
So, I call API like this:
AxiosServices.post(ApiUrlServices.SOCIALS_UPDATE_LINKS(UserInfo.userId), payload, false)
.then(response => {})
What i figured out that return axios(error.response.config); is not sending authorization token in API request headers and trying request infinitely. But consoling error.response.config shows token sets in the config correctly.
Adding an additional modification of axios request, I solved my problem.
axios.interceptors.request.use(request => {
// Edit request config
let usersData = JSON.parse(localStorage.getItem('userData'));
request.headers['Authorization'] = `${usersData.idToken}`;
return request;
}, error => {
return Promise.reject(error);
});

How to handle authorization headers on API call in React?

I'm trying to make a GET request to retrieve Total balance for a payment summary. I get a 401 unauthorized error on the console.
const getPay = () => {
Axios({
method: "GET",
url: `apiEndpoint/${variable}`,
headers: {
'Content-Type': 'application/json',
'x-access-token': "Available upon request"
}
})
.then((response) => {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
useEffect(() => {
getPay()
}, [])
The API docs states "Every request to any of the endpoints must contain the headers." The headers above were stated but I get an error 401(Unauthorized). please how do I go about this?
Just add Authorization in your headers
const getPay = () => {
Axios({
method: "GET",
url: `apiEndpoint/${variable}`,
headers: {
'Content-Type': 'application/json',
'x-access-token': "Available upon request",
Authorization: `Bearer YOUR_TOKEN`
}
})
.then((response) => {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
useEffect(() => {
getPay()
}, [])
Also, It is better to implement axios interceptors so that you dont have to pass headers in each call
// Request interceptor
API.interceptors.request.use(
async axiosConfig => {
const token = await getToken()
if (token && axiosConfig.headers) {
axiosConfig.headers.Authorization = `Bearer ${token}`
}
return axiosConfig
},
error => Promise.reject(error),
)

Unable to get response using fetch in React

I am trying to call 3rd party API, to fetch some data. I am getting the response in Postman, but not getting expected response when I execute my code.
I tried in 2 ways. Both ways I am getting "Promise pending".What could be the reason??
//request.js
Method 1
export const callSearchGiftsAPI = inputs => dispatch => {
dispatch(searchGifts());
let url = new URL(GIFT_SEARCH_API_URL),
params = {
apiKey: GIFT_SEARCH_API_KEY,
query: inputs.item,
country: 'us',
itemsPerPage: 3
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
return new Promise((resolve, reject) => {
setTimeout(() => resolve(
fetch(url, {
method: 'GET',
// mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
Authorization: `secret ${SECRET}`
}
})
.then(res => {
if (!res.ok) {
return Promise.reject(res.statusText);
}
console.log("hi", res.json());
return res.json();
})
.then(gifts => dispatch(searchGiftsSuccess(gifts)))
.catch(err => dispatch(searchGiftsError(err)))), 500)
});
}
Method 2:
export const callSearchGiftsAPI = inputs => dispatch => {
dispatch(searchGifts());
let url = new URL(GIFT_SEARCH_API_URL),
params = {
apiKey: GIFT_SEARCH_API_KEY,
query: inputs.item,
country: 'us',
itemsPerPage: 3
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
fetch(url, {
method: 'GET',
// mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
Authorization: `secret ${SECRET}`
}
})
.then(res => {
if (!res.ok) {
return Promise.reject(res.statusText);
}
console.log('result', res.json());
return res.json();
})
.then(gifts => dispatch(searchGiftsSuccess(gifts)))
.catch(err => dispatch(searchGiftsError(err)));
};
//form.js
class Form extend React.Component{
onSubmit(values) {
const inputs = Object.assign({}, values);
return this.props.dispatch(callSearchGiftsAPI(inputs));
}
//Remaining code
}
Also please note that I have installed CORS plugin in Chrome, to allow the request.If I disable it and add mode:'no-cors' I am getting as 401 unauthorized.What else am I supposed to do?
What happens is that you are creating a new Promise and returning it, but you are not waiting for it to resolve. You can either use then of the new async/await syntax to get the correct result :
onSubmit = async values => {
const inputs = Object.assign({}, values);
return await this.props.dispatch(callSearchGiftsAPI(inputs));
}
The code above will work with your first method.
Since your second method does not return anything, you will never get your result, you need to return your fetch's result and apply the code I gave above :
return fetch(url, {
This worked.
I was trying to put console.log in the wrong place and hence was not able to see the response properly.
export const callSearchGiftsAPI = inputs => dispatch => {
dispatch(searchGifts());
let url = new URL(GIFT_SEARCH_API_URL),
params = {
apiKey: GIFT_SEARCH_API_KEY,
query: inputs.item,
country: 'us',
itemsPerPage: 3
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
console.log(url);
return fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `secret ${SECRET}`
}
})
.then(res => {
console.log('result');
return res.json();
})
.then(response => {
console.log(response); // changed
dispatch(searchGiftsSuccess(response.items));
})
.catch(err => dispatch(searchGiftsError(err)));

How to add Function in POST Headers

The target is sending a POST request with Autorization header contains token.
It's function:
export function authHeader() {
// return authorization header with jwt token
let user = JSON.parse(localStorage.getItem('user'));
if (user && user.token) {
return { 'Authorization': 'Bearer ' + user.token };
} else {
return {};
}
}
Here is async function send to server:
export async function submitToServer(values){
try{
let response = await fetch('http://localhost:50647/fund/submitfund', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type' : 'application/json',
authHeader()
},
body: JSON.stringify(values),
});
let responseJson = await response.json();
return responseJson;
} catch (error) {
console.error(error);
}
}
How can I add authHeader() to headers in POST to correctly authorize this request?
Use ... spread operator like, ...authHeader(). Your authHeader function returns an object { 'Authorization': 'Bearer ' + user.token } or {}. What you want is to merge it to the object you attached with the headers key, so ... operator is the correct tool here.
So your code will be:
export async function submitToServer(values) {
try {
let response = await fetch('http://localhost:50647/fund/submitfund', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
...authHeader()
},
body: JSON.stringify(values),
});
let responseJson = await response.json();
return responseJson;
} catch (error) {
console.error(error);
}
}

React-Native : How to get callback of api call in another class

I am calling a web service
Here is my code:
var result;
export function callPostApi(urlStr, params)
{
fetch(urlStr, {method: "POST", headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(params)})
.then((response) => response.json())
.then((responseData) => {
result = JSON.stringify(responseData)
})
.catch((error) => { console.error(error);
Alert.alert('Alert Title failure' + JSON.stringify(error))
})
.done();
return result
}
I am calling from here:
callapi(){
var dict = {
email: 'at#gmail.com',
password: '123456',
}
result = callPostApi('http://demo.com', dict)
}
Currently, it is calling in Async mode that we want but code is written below this method getting execute immediately after calling of above method
i want callback when result from sever has received so that i can execute code written below the above method is execute after receiving response from server.
You need to use Promises.
Change your callPostApi function to return a Promise, then you can chain additional then, catch and finally calls.
export function callPostApi(urlStr, params) {
return fetch(urlStr, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(params)
})
.then((response) => response.json())
.then((responseData) => {
result = JSON.stringify(responseData)
})
.catch((error) => {
console.error(error);
Alert.alert('Alert Title failure' + JSON.stringify(error))
});
}
callapi() {
callPostApi('http://demo.com', {
email: 'at#gmail.com',
password: '123456',
})
.then((response) => {
// Continue your code here...
});
}

Resources