RTK query and response from server - javascript

updateTagCurrentValue: builder.mutation<any, {path: string, body: updateTagCurrentValueBody}>({
query: (args) => {
const {path, body} = args
return ({
url: `/v2/tags/${path}/values/current`,
method: 'PUT',
body: body,
})
},
transformResponse: (response) => {
return response
}
})
I am new in RTK, this mutation is working well, but I can not understand how to get a response from server? I see it in inspect network tab, I see my added data in the server, but the response comes null
const [updateTagCurrentValue, {error, isSuccess}] = useUpdateTagCurrentValueMutation()
const onSubmit: SubmitHandler = async (data) => {
let body: updateTagCurrentValueBody = {
value: {value: JSON.stringify(data)}
}
try {
let response = await updateTagCurrentValue({path: 'test', body}).unwrap();
console.log(response)
} catch (err) {
console.log(err)
}
}
I searched for solutions, and some people said add .unwrap() at the end of the call, but it didn't help. transformResponse also changes nothing, isSuccess changes from false to true after the second submission...

Related

Adyen UPI client integration get status

I am somehow trying to get the status (error,success) after paying through the UPI app. I already end up in the onAdditionalDetails() function but here I somehow don't have the possibility to query the status. Is there maybe something needed to get this information in the state object?
async initAdyen_newurl() {
let config = null;
config = {
...this.config.adyenConfig,
onPaymentCompleted: (result, component) => {
console.info("onPaymentCompleted");
console.info(result, component);
},
onError: (error, component) => {
console.error("onError");
console.error(error.name, error.message, error.stack, component);
},
onAdditionalDetails: (state, component) => {
const actionUrl = "hardcoded for the moment"
const obj = {
paymentMethodType: component.props.paymentMethodType,
url: actionUrl,
method: "post",
type: "redirect",
paymentData: component.props.paymentData
}
component.props.createFromAction(obj, {}).mount("#id");
},
};
AdyenCheckout(config)
.then((checkout) => {
// init stuff
})
.catch((error) => {
console.error(`url failure ${error.message}`);
});
},
I can also redirect to the next page using createFromAction(), but this just happens in both Success and Error. However, this should only happen in Success. I hope that was somehow understandable. Many Thanks
edited: i am using version 5.23.0
The flow involves an additional step (3DS) so the onAdditionalDetails handler is invoked. From there you can add an extra call to /payments/details to fetch the payment status.
The response includes the resultCode to inform the shopper of the payment status.
Here is an example:
...
onPaymentCompleted: (result, component) => {
handleServerResponse(result, component);
},
onAdditionalDetails: async (response, _component) => {
// call server
const paymentDetailsResponse = await callServer("/api/paymentDetails", response);
// obtain payment status
const result = paymentDetailsResponse.resultCode
},
onError: (error, component) => {
console.error(error.name, error.message, error.stack, component);
}
// Calls your server endpoints
async function callServer(url, data) {
const res = await fetch(url, {
method: "POST",
body: data ? JSON.stringify(data) : "",
headers: {
"Content-Type": "application/json",
},
});
In the backend perform the paymentsDetails call to obtain the Payment status from the Adyen platform:
// Check payment result
app.post("/api/paymentDetails", async (req, res) => {
try {
const response = await checkout.paymentsDetails({
details: req.body.data.details,
paymentData: req.body.data.paymentData,
});
res.json(response);
} catch (err) {
console.error(`Error: ${err.message}, error code: ${err.errorCode}`);
res.status(err.statusCode).json(err.message);
}
});
See Confirm an additional action on your server

Chaining an axios.get call to use the response for an axios.all multiple request

I'm having difficulties to understand how Shall I handle this type of calls. I need an initial axios.get call and loop through to make an axios.all call. This is my code:
export async function getServerSideProps(context) {
const axios = require("axios");
const options = {
method: 'GET',
url: 'xxxxx',
params: { id_user: 'xxxxx' },
headers: {
'X-RapidAPI-Host': 'xxxxxxx',
'X-RapidAPI-Key': 'xxxxxxx'
}
};
const res = axios.request(options).then(function (response) {
axios.all(response.data.users.map(user => {
axios.get('xxxxxxx', {
params: { response_type: 'short', ig: user.username, corsEnabled: 'true' },
headers: {
'X-RapidAPI-Host': 'xxxxx',
'X-RapidAPI-Key': 'xxxxxxx'
}
})
})).then(res => {
return res.data
})
})
const payload = await res;
I have an error on the page when I try to console log the payload. What's going worng with my call?
Looks like you need a return inside your map.
The below code worked for me and the unique params were updated on each request. Once you prepare your series of endpoints or whatever is unique for each request (user data per your sample code) you map over the relevant data and make all your get requests. The result returned will be an array of the responses you get back from each request once all of the requests have finished.
Regarding chaining together requests, you can use any number of .then() to kick off other actions. You mention needing an id from an initial get request, so here is a solution based on that example.
Hope you find it helpful.
const users = [{ username: '1' }, { username: '2' }, { username: '3' }];
axios
.get('https://jsonplaceholder.typicode.com/posts')
.then((res) => {
console.log(res);
// simulating getting some id you need...
const id = res.data[4].id;
console.log(id);
return id;
})
.then((id) => {
axios
.all(
users.map((user) => {
return axios.get('https://jsonplaceholder.typicode.com/posts', {
params: {
response_type: 'short',
// just an example of using id...
importantId: id,
ig: user.username,
corsEnabled: 'true',
},
headers: {
'X-RapidAPI-Host': 'xxxxxxx',
'X-RapidAPI-Key': 'xxxxxxx',
},
});
})
)
.then((res) => {
console.log(res);
});
});

How to optimize an API fetch to be less redundant

I'm building a React App which consumes an API and what I build for now is 2 functions which both GET the same URL but changing the second part of the API Endpoint like URL/?search or URL/?i=123 but what I would like to achieve is to have less redundant code so I was wondering to make one function which just takes the same URL and change the second part of the URL based on the call.
By the way, this approach gives me problems.
The code I did originally was this:
import {API_MOVIE_URL, API_KEY} from "./ApisConst";
export const getMoviesBySearch = async search => {
try {
const url = `${API_MOVIE_URL}?apikey=${API_KEY}&${search}`;
const response = await fetch(url);
const json = await response.json();
return json;
} catch {
return {
success: false,
result: [],
message: "There is an issue to get data from server. Please try again later.",
};
}
};
export const getMoviesInfo = async movieID => {
try {
const url = `${API_MOVIE_URL}?apikey=${API_KEY}&i=${movieID}&plot`;
const response = await fetch(url);
const json = await response.json();
return json;
} catch {
return {
success: false,
result: [],
message: "There is an issue to get data from server. Please try again later.",
};
}
};
And the change I tried is:
const fetchAPI = async ({type, query}) => {
const queryParams = {
byString: `&${query}`,
byMovieId: `&i=${query}&plot`,
};
const endpoint = `${API_MOVIE_URL}?apikey=${API_KEY}${queryParams[type]}`;
console.log("fetching", endpoint);
return fetch(endpoint)
.then(res => res)
.catch(() => ({
success: false,
result: [],
message: "There is an issue to get data from server. Please try again later.",
}));
};
export const getMoviesBySearch = async search =>
await fetchAPI({type: "byString", query: search});
export const getMoviesInfo = async movieID =>
await fetchAPI({type: "byMovieId", query: movieID});
But this second approach gives me an error in the console which is:
Response {type: "cors", url: "https://www.omdbapi.com/?apikey=API_KEY&s=harry+potter&type=movie", redirected: true, status: 200, ok: true, …}
body: (...)
bodyUsed: false
headers: Headers {}
ok: true
redirected: true
status: 200
statusText: ""
type: "cors"
url: "https://www.omdbapi.com/?apikey=API_KEY&s=harry+potter&type=movie"
The first approach works perfectly but the second one none and trying to get a solution but cannot really think what to do to get this code better optimized.
Since the queries are identical except for the url, create a query generator (createMoviesQuery) that accepts a function that generates the url (urlGenerator), and returns a query function
Example (not tested):
import {API_MOVIE_URL, API_KEY} from "./ApisConst";
const createMoviesQuery = urlGenerator => async (...params) => {
try {
const url = urlGenerator(...params);
const response = await fetch(url);
const json = await response.json();
return json;
} catch {
return {
success: false,
result: [],
message: "There is an issue to get data from server. Please try again later.",
};
}
};
export const getMoviesBySearch = createMoviesQuery((search) => `${API_MOVIE_URL}?apikey=${API_KEY}&${search}`);
export const getMoviesInfo = createMoviesQuery((movieID) => `${API_MOVIE_URL}?apikey=${API_KEY}&i=${movieID}&plot`);

Redux Thunk - Change state before REST request

I am quite new to Redux Thunk and have an issue that I want to update a contract with a 'FileList' (file appendix), but if I use JSON.stringify the file will have a 0 value. If I convert the file to Base64 this problem is solved, but the PUT request is performed before the file is converted.
I searched a lot about Redux Thunk and think it might be some issue with Dispatch, I tried quite a lot and didn't become much wiser. Most of the things that I tried returned: "Actions must be plain objects. Use custom middleware for async actions."
Would appreciate some help or some search suggestions..
ps. contract.answers[0].answer[0] is the file. This acquires some refactoring, but first it needs to work.
const toBase64 = (file) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
export function updateContract(contract) {
const base64File = toBase64(contract.answers[0].answer[0]);
base64File.then((value) => {
contract.answers[0].answer[0] = value; //Set file as base64
});
return {
type: SAVE,
fetchConfig: {
uri: contract._links.self,
method: 'PUT',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(contract), // Does not handle files
failureHandler(error) {
const {
details,
status,
} = error;
// If the contract was invalid, throw form errors:
if (status.code === 400 && details) {
// Map the question ids to fields:
throw new SubmissionError(Object.keys(details).reduce(
(acc, questionId) => {
acc[`question${questionId}`] = details[questionId];
return acc;
},
{},
));
}
return {
type: SAVE_FAILURE,
error,
};
},
successHandler(json) {
return {
type: SAVE_SUCCESS,
data: json,
};
},
},
};
}
Kind regards,
Gust de Backer
This happen because toBase64 return a Promise and itself is async, so in your case is necessary encapsule inside a new then.
export function updateContract(contract) {
const base64File = toBase64(contract.answers[0].answer[0]);
base64File.then((value) => {
contract.answers[0].answer[0] = value; //Set file as base64
});
return (dispatch) => {
base64File.then(() => dispatch({
type: SAVE,
fetchConfig: {
uri: contract._links.self,
method: 'PUT',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(contract), // Does not handle files
failureHandler(error) {
const {
details,
status,
} = error;
// If the contract was invalid, throw form errors:
if (status.code === 400 && details) {
// Map the question ids to fields:
throw new SubmissionError(Object.keys(details).reduce(
(acc, questionId) => {
acc[`question${questionId}`] = details[questionId];
return acc;
}, {},
));
}
return {
type: SAVE_FAILURE,
error,
};
},
successHandler(json) {
return {
type: SAVE_SUCCESS,
data: json,
};
},
},
}))
};
}
Yes, the redux accept a function as return, that function receive a dispatch on params, you can use it to dispatch the request after convert is ready :)

fetch not executing with correct params - React Native

So I have a React Native app, making calls to my own external api via the fetch() native API. I am encountering a strange issue with my requests not being processed by fetch() correctly in only one context.
The calls are supposed to POST to /api/token_login.
Here is how I make my calls in the app:
#/src/services/post.js
import headers from './headers';
const APIURL = '******/api';
export default async (path, data, callback) => {
try {
const postData = {
method: 'POST',
credentials: 'include',
headers: new Headers(headers),
body: JSON.stringify(data)
};
const requestURL = `${APIURL}/${path}`;
const request = new Request(requestURL, postData);
const response = await fetch(request);
const res = await response.text();
if (response.ok) {
callback(null, res);
} else {
const error = res;
callback(error, null);
}
} catch (error) {
console.log('caught error: ', error);
}
};
#/src/services/auth.js
import post from './post';
export function TokenLogin(data, callback) {
post('token_login', data, callback);
}
...other functions
#/src/containers/Login.js
const data = {
user: {
auth_token: token,
},
};
return TokenLogin(data, (err, response) => {
const res = JSON.parse(response);
... do stuff
};
This function gets called on componentDidMount under certain conditions, which is the expected behavior. However, every day or so it suddenly stops sending the request to the passed in path, and sends a GET to /api/login instead. Changing the path passed into the function changes the behavior back to the expected one (i.e., passing in flurgl sends a POST request to .../api/flurgl with the body passed in correctly. Here is some debugging info:
// the logs:
=> Request method: POST url: https://*****/api/token_auth
=> Response object:
=> Response {type: "default", status: 404, ok: false, statusText: undefined, headers: Headers, …}
bodyUsed: true
headers: Headers {map: {…}}
ok: false
status: 404
statusText: undefined
type: "default"
url: "https://*******/api/login"

Categories

Resources