I want to pass a parameter value from one API-Request to 2nd API-request so that 2nd api display result accordingly: Here is my function componentWillMount:
componentWillMount() {
axios.post('https://APISITE/api/Auth/AuthorizeByApplication?applicationId=b72fc47a-ef82-4cb3-8179-2113f09c50ff&applicationSecret=e727f554-7d27-4fd2-bcaf-dad3e0079821&token=cd431b31abd667bbb1e947be42077e9d')
.then((response) => { console.log(response.data); });
axios.get('https://APISITE//api/Stock/GetStockItems',
{
params: {
keyWord: 454534534543,
locationId: '',
entriesPerPage: 100000,
pageNumber: 1,
excludeComposites: true,
//add other params
},
headers:
{ Authorization: 'asdfasdsfdfdfdfsfsdxxx'
}
//}).then((response) => { console.log(response.data); });
}).then((response) => this.setState({ products: response.data }));
axios.get('https://APISITE//api/Stock/GetStockLevel', {
params: {
stockItemId: '2f80b45c-85ff-449b-9ad6-ffcc4bb640dd',
},
headers:
{ Authorization: 'asdfasdsfdfdfdfsfsdxxx'
}
// }).then(response => console.log(response));
}).then((response) => this.setState({ racks: response.data }));
}
Value in stockItemId is passed as static value and result displayed in console correctly. How can get stockItemId's value dynamically from 1st-api request?
Edit: Below is data result screenShots of passing stockItemId directly in api and getting from 1st api.
Getting from 1st api: stockItemId: stockItems.data.StockItemId : http://prntscr.com/i7k0j7
Directly passing value of stockItemId screenshot- stockItemId: '2f80b45c-85ff-449b-9ad6-ffcc4bb640dd' http://prntscr.com/i7jyq7
You need to handle the response data from within the then functions.
Notice the way the response from each request is passed into the following then where it can easily used.
componentWillMount() {
axios
.post('https://APISITE/api/Auth/AuthorizeByApplication?applicationId='app id'&applicationSecret='app secret'&token='app token'')
.then((authData) => {
console.log(authData.data);
return axios.get('https://APISITE//api/Stock/GetStockItems', {
params: {
keyWord: 5055967419551,
locationId: '',
entriesPerPage: 100000,
pageNumber: 1,
excludeComposites: true,
},
headers: {
Authorization: '0f32ae0d-c4e0-4aca-8367-0af88213d668'
}
})
})
.then((stockItems) => {
this.setState({ products: stockItems.data })
return axios.get('https://APISITE//api/Stock/GetStockLevel', {
params: {
stockItemId: stockItems.data.stockItemId,
},
headers: {
Authorization: '0f32ae0d-c4e0-4aca-8367-0af88213d668'
}
})
})
.then((stockLevel) =>
this.setState({ racks: stockLevel.data })
)
}
(This code is untested!)
First thing never use componentWillMount component life cycle method to set the component state or call any api request for these purpose use componentDidMount for more reading which life cycle use for which purpose read this article and Secondly just add the second api request inside the first api request response with different name response name as given below:
componentDidMount() {
axios.post('https://APISITE/api/Auth/AuthorizeByApplication?
applicationId='app id'&applicationSecret='app secret'&token='app token'')
.then((responseFirst) => {
axios.get('https://APISITE//api/Stock/GetStockItems', {
params: {
keyWord: 5055967419551,
locationId: '',
entriesPerPage: 100000,
pageNumber: 1,
excludeComposites: true,
},
headers: {
Authorization: '0f32ae0d-c4e0-4aca-8367-0af88213d668'
}
}).then((responseSecond) => this.setState({ products: responseSecond.data }));
axios.get('https://APISITE//api/Stock/GetStockLevel', {
params: {
stockItemId: responseFirst.data.stockItemId,
},
headers: {
Authorization: '0f32ae0d-c4e0-4aca-8367-0af88213d668'
}
}).then((responseThird) => this.setState({ racks: responseThird.data }));
});
}
if you are using redux then read redux documentation to handle async type actions and how to handle it.
Related
i have screen when user have buttons to change hes Name, or phone
i have function that handle if the user clicked on change name or phone
now i want to conditionally implement a PUT req, that change only the field that the user clicked,
for example look what exactly i want to do: (look at the if)
how can i do that conditinally field?
const updateUser = dispatch => async (userId, param, value, token) => {
dispatch({ type: "loading", payload: true });
try {
const res = await indexApi.put(
`/user/${userId}`,
{
if(param==="name") name: value,///////////////here
if(param==="phone")phone: value ////////////here
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
note that i also tried to do :
name: (param===name) ? value: res.data.user.name
phone: (param===phone) ? value: res.data.user.phone
I mean take the data from the server , but the server does not return me and sends me an UNDEFINED comment res.data.user.name undefined................
probably its not enough to get it until the func finish or something
if you want to do object with specified property name try this:
{
[param]: value
}
In brackets value of variable param become 'name' or 'phone' in your case.
const updateUser = dispatch => async (userId, param, value, token) => {
dispatch({ type: "loading", payload: true });
try {
const res = await indexApi.put(
`/user/${userId}`,
{
[param]: value
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
Vuex state is sometimes empty (undefined), especially when I refresh the page. And sometimes it works.
action:
getSkills(context) {
let url = "/skills";
const headers = {
"x-api-key": process.env.VUE_APP_SIRH_X_API_KEY,
Authorization: localStorage.getItem("access_token"),
};
return axios({
method: "get",
url: url,
headers: headers,
}).then((response) => {
context.commit("getSkill", response.data.data.skills);
}).catch((e) => {
console.log(e);
});
},
getter:
Skills: (state) => state.Skills,
mutation :
getSkill(state, skills) {
state.Skills = skills;
},
state :
Skills: [],
and the vue :
computed: {
...mapState({}),
...mapGetters(["Candidate", "Skills"])
},
mounted() {
this.getSkills();
this.id = this.$route.params.id;
this.Skills.forEach(element => this.skill_list.push(element.skill_name));
},
methods: {
...mapActions(["attachSkillCandidate", "getSkills"]),
}
Can anyone help me to solve this issue ?
Thanks!
The getSkills action is performing an asynchronous request. You need to wait for the request to finish before you can access this.Skills otherwise the data will not be set yet.
You need async and await (the "modern" solution):
async mounted() {
await this.getSkils();
this.id = this.$route.params.id;
this.Skills.forEach(element => this.skill_list.push(element.skill_name));
}
or:
mounted() {
this.getSkils().then(() => {
this.id = this.$route.params.id;
this.Skills.forEach(element => this.skill_list.push(element.skill_name));
});
}
I wrote functions for sending requests using redux api middleware. What does the POST function look like instead of GET?
RSAA getOrdersRequest(){
return RSAA(
method: 'GET',
endpoint: 'http://10.0.2.2:80/order',
types: [
LIST_ORDERS_REQUEST,
LIST_ORDERS_SUCCESS,
LIST_ORDERS_FAILURE,
],
headers: {
'Content-Type':'application/json',
},
);
}
ThunkAction<AppState> getOrders() => (Store<AppState> store) => store.dispatch(getOrdersRequest());
my function is written in dart, but the language of the example is not important,
thanks for any help
For making async calls, you should use middlewares like redux-thunk. I'll be using JavaScript here.
All you need to know about thunk is that redux-thunk allows your action creator(like postOrder) to return a function which then dispatches respective actions(object with a type and payload/data property) to the store. You can dispatch as many actions as you like.
POST is just a HTTP verb that I'm using to post an order, as you could see down here. Firstly, POST_ORDERS_REQUEST is the beginning of your request, in which, you could show loading... state or a spinner in your application. So, this action fires off, orderReducer checks what type of action has arrived, and in turn, acts accordinly and stores the data in the redux-store. I'm sure you know basic redux, so it might not be a problem for you to understand all this. The other two actions work the same way.
export const postOrder = () => {
return async (dispatch) => {
dispatch({
type: POST_ORDER_REQUEST
})
try {
const res = await axios.post("http://10.0.2.2:80/order",
{
headers: {
"Content-Type": "application/json",
}
})
dispatch({
type: POST_ORDER_SUCCESS,
data: { order: res.data.order }
})
} catch (err) {
dispatch({
type: POST_ORDER_FAILURE,
data: { error: `Order failed with an ${err}` }
})
}
}
}
You could accordingly create your orderReducer, for example:
const initialState = {
isLoading: false,
myOrder: null,
error: null
}
export const orderReducer = (state = initialState, action) => {
switch (action.type) {
case POST_ORDER_REQUEST:
return {
...state,
isLoading: true,
error: null
}
case POST_ORDER_SUCCESS:
return {
...state,
isLoading: false,
myOrder: action.data.order,
error: null
}
case POST_ORDER_FAILURE:
return {
...state,
isLoading: false,
error: action.error
}
default:
return state
}
}
You can read these good articles on Redux that you might like:
https://daveceddia.com/what-is-a-thunk/
https://daveceddia.com/where-fetch-data-redux/
since accepted response had nothing to do with redux api middleware which is made in order to reduce "boilerplatish" and repetitive thunk code, you can use createAction from redux-api-middleware like:
import { createAction } from "redux-api-middleware";
export const getOrders = () =>
createAction({
endpoint: 'http://10.0.2.2:80/orders',
method: "GET",
types: ['GET_ORDERS_PENDING', 'GET_ORDERS_SUCCESS', 'GET_ORDERS_FALED'],
});
export const getOrderById = (id) =>
createAction({
endpoint: `http://10.0.2.2:80/orders/${id}`,
method: "GET",
types: ['GET_ORDER_BY_ID_PENDING', 'GET_ORDER_BY_ID_SUCCESS', 'GET_ORDER_BY_ID_FALED'],
});
export const submitOrder = (name, price) =>
createAction({
endpoint: 'http://10.0.2.2:80/orders',
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: name,
price: price,
}),
types: ['SUBMIT_ORDER_PENDING', 'SUBMIT_ORDER_SUCCSESS', 'SUBMIT_ORDER_FAILED'],
});
in cases where you could use more handling than simple api service calling you can always combine it with thunk like this
I'm making a axios get call to a web api that is looking to have the query string parameters in this specific format which seems uncommon: [0].mfr=mfr0&[0].mpn=mpn0&[1].mfr=mfr1&[1].mpn=mpn1
I've been trying to use the Qs library to stringify the params in the paramsSerializer option.
parts = [{ mfr: "mfr0", mpn: "mpn0" }, { mfr: "mfr1", mpn: "mpn1" }]
findParts(parts, token) {
return axios
.request({
url: "https://<serveraddress>/api/v1/parts/findparts",
method: "get",
params: parts,
headers: {
Authorization: "Bearer " + token,
"Content-Type": "text/plain"
}
})
.catch(error => {
console.log(error);
Vue.notify({
type: "error",
title: "Unable to find parts",
text: "Unable to find parts"
});
});
}
result
0={"mfr":"mfr0","mpn":"mpn0"}&1={"mfr":"mfr1","mpn":"mp1"}
paramsSerializer: function(params) {
return qs.stringify(params);
},
or
paramsSerializer: function(params) {
return qs.stringify(params, { arrayFormat: "brackets" });
},
or
paramsSerializer: function(params) {
return qs.stringify(params, { arrayFormat: "indices" });
},
result
0[mfr]=mfr0&0[mpn]=mpn0[mfr]=mfr1&1[mpn]=mpn1
paramsSerializer: function(params) {
return qs.stringify(params, { allowDots: true });
},
result
0.mfr=mf0&0.mpn=mpn0&1.mfr=mfr1&1.mpn=mpn1
I can create a custom paramsSerializer but I was wonder if there a way to manipulate qs or the passed parts array to get the correct query string results without having to manually create the query string and url encode the values?
I created two custom endpoints with Loopback.
Account.deleteAllHearingTests = function (req, callback) {
console.log('here comes the req to delete all hearing tests', req);
Account.findById(req.accessToken.userId)
.then(account => {
if (!account) {
throw new Error('cannot find user');
}
return app.models.HearingTest.updateAll({ accountId: account.id }, { isDeleted: new Date() });
})
.then(() => {
callback(null);
})
.catch(error => {
callback(error);
})
}
Account.remoteMethod(
'deleteAllHearingTests', {
http: {
path: '/clearHearingTests',
verb: 'post'
},
accepts: [
{ arg: 'req', type: 'object', http: { source: 'req' } }
],
returns: {}
}
);
the second one looks like this.
Account.deleteSingleHearingTest = function (req, callback) {
// console.log('accounts.js: deleteSingleHearingTest: are we being reached????', req)
Account.findById(req.accessToken.userId)
.then(account => {
if (!account) {
throw new Error('Cannot find user');
}
console.log('account.js: deleteSingleHearingTest: req.body.hearingTestId N: ', req.body.hearingTestId);
return app.models.HearingTest.updateAll({ accountId: account.id, id: req.body.hearingTestId }, { isDeleted: new Date() });
})
.then(() => {
callback(null);
})
.catch(error => {
callback(error);
});
}
Account.remoteMethod(
'deleteSingleHearingTest', {
http: {
path: '/deleteSingleHearingTest',
verb: 'post'
},
accepts: [
{ arg: 'req', type: 'object', description: 'removes a single hearing test', http: { source: 'req' } }
],
description: 'this is the end point for a single delete',
returns: {}
}
);
};
The first custom method returns a 401 status response when I make the initial fetch. The second returns a 200.
Inside my actions file the first method is called with something that looks like this:
export function deleteAllHearingTests() {
return (dispatch, getState) => {
let state = getState();
if (!state.user || !state.user.accessToken || !state.user.accessToken.id || !state.user.accessToken.userId) {
console.debug('deleteAllHearingTests', state.user);
// TODO: ERROR
return;
}
fetch(SERVERCONFIG.BASEURL + '/api/Accounts/clearHearingTests?access_token=' + state.user.accessToken.id, {
method: 'POST',
headers: SERVERCONFIG.HEADERS
})
.then(response => {
console.log('here is your response', response);
if (response.status !== 200) {
throw new Error('Something is wrong');
}
return response.json()
})
the second method is called with
export const deleteSingleHearingTest = (hearingTestNumber) => {
return (dispatch, getState) => {
let state = getState();
if (!state.user || !state.user.accessToken || !state.user.accessToken.id || !state.user.accessToken.userId) {
console.debug('writeTestResult', state.user);
// TODO: ERROR
return;
}
console.log('single delete ', SERVERCONFIG.BASEURL + '/api/Accounts/deleteSingleHearingTest?access_token=' + state.user.accessToken.id)
fetch(SERVERCONFIG.BASEURL + '/api/Accounts/deleteSingleHearingTest?access_token=' + state.user.accessToken.id, {
method: 'POST',
headers: SERVERCONFIG.HEADERS,
body: JSON.stringify({ "hearingTestId": hearingTestNumber })
})
.then(response => {
console.log('getting response from initial fetch inside deleteSingleReqport', response);
They are nearly identical, however, one works..the other fails. What are some possible causes for the 401?
Did you try to call those methods with external tool like a postman, so you would exactly know if you don't miss access_token or something else? Also, when you compare code from one function and another, you can see that you are colling the updateAll with different arguments. It's hard to say without original code, but maybe the issue is there? Compare below:
return app.models.HearingTest.updateAll(
{ accountId: account.id },
{ isDeleted: new Date() });
return app.models.HearingTest.updateAll(
{ accountId: account.id, id: req.body.hearingTestId },
{ isDeleted: new Date() });
Additionally, in fetch method they are also diffferences, you are missing in one case the below:
body: JSON.stringify({ "hearingTestId": hearingTestNumber })
What you could also do to debug and to provide more data is to run server in debug mode by calling:
export DEBUG=*; npm start