Get vuex action response object in component context - javascript

I'm trying to get the response object resulting of calling a vuex action with axios, I need the response in my object but it says undefined for some reason.
In my component method:
mounted()
{
console.log(this.$options.name+' component successfully mounted');
this.$store.dispatch(this.module+'/'+this.action, this.payload)
.then((response) =>
{
console.log(response);
this.items = response.data.data;
this.pagination = response.data.pagination;
});
},
My vuex action:
list({ commit }, payload)
{
commit( 'Loader/SET_LOADER', { status:1 }, { root: true });
return axios.get('/api/posts', { params: payload })
.then((response) => {
commit('Loader/SET_LOADER', { status:2, response:response }, { root: true });
console.log(response);
commit('SET_POSTS', response.data.data.data );
commit('SET_PAGINATION', response.data.pagination );
})
.catch((error) => {
commit('Loader/SET_LOADER', { status:3, errors: error }, { root: true });
throw error;
});
},
Using vuex state is not an option, I want to use the component data properties items and pagination instead.

Return promise to get the response in the component
list({ commit }, payload)
{
commit( 'Loader/SET_LOADER', { status:1 }, { root: true });
return new Promise((resolve,reject)=>{
axios.get('/api/posts', { params: payload })
.then((response) => {
commit('Loader/SET_LOADER', { status:2, response:response }, { root: true });
console.log(response);
commit('SET_POSTS', response.data.data.data );
commit('SET_PAGINATION', response.data.pagination );
resolve(response);
})
.catch((error) => {
commit('Loader/SET_LOADER', { status:3, errors: error }, { root: true }); reject(error);
throw error;
});
})
},
Using async
async list({commit}, payload) {
commit('Loader/SET_LOADER', {status: 1}, {root: true});
try {
let response = await axios.get('/api/posts', {params: payload});
commit('Loader/SET_LOADER', {status: 2, response: response}, {root: true});
console.log(response);
commit('SET_POSTS', response.data.data.data);
commit('SET_PAGINATION', response.data.pagination);
return response;
} catch (e) {
commit('Loader/SET_LOADER', {status: 3, errors: error}, {root: true});
throw error;
}
}

Related

waiting fetch to get the data

On a vue application, on a component, calling API to get some data... the problem is that getting undefined, before the call ends... Possible needed aync/await but getting error when adding
//component code (login.vue)
import store from "#/store";
const { response, error } = store.postTO(url, [{id: "button1"}, {id: "button2"}, {id: "button3"}]);
if (response) {
console.log(response);
} else {
console.warn(error);
}
//store.js
export default {
user : null,
postTO
}
function postTO(url, postData) {
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: JSON.stringify(postData)
};
return fetch(url, requestOptions).then(response =>
response.json().then(data => ({
data: data,
status: response.status
})
).then(res => {
console.log(res.data);
return {response : res.data, error : "test"};
}))
.catch(error => {
return {response : "test", error : error};
});
}
illustrated
In the component you have to wait for the fetch by putting an await before the store.posTo

Mutating a specific piece of state from the mutation in VUEX

I'm having a hard time doing this and I'm sure it's simple but I can't get it to work. I have a toggle switch with boolean value that I am successfully making it work from the Vue file but obviously vuex is yelling cause any prop change needs to be mutated in the vuex file. Here is the relevant code:
Vue file
<template>
<workstation
v-for="(workstation, index) in hStation.workstations" :key="index"
:id="workstation.recordId"
:close="workstation.closed"
#toggledState="toggleState(workstation)"
></workstation>
</template>
<script>
methods: {
...mapActions("pod", ["updateWorkstation"]),
toggleState(workstation) {
workstation.closed = !workstation.closed;
this.updateWorkstation({
recordId: workstation.recordId,
closed: workstation.closed
})
.then(response => {
console.log("id: ", workstation.recordId);
console.log("closed: ", workstation.closed);
})
.catch(error => {
console.log("error: ", error);
});
},
},
</script>
The vuex file simplified
import { axiosInstance } from "boot/axios";
export default {
namespaced: true,
state: {
workstation: []
},
getters: {
singleWorkstation: state => {
return state.workstation;
}
},
actions: {
updateWorkstation: ({ commit }, payload) => {
return new Promise((resolve, reject) => {
axiosInstance
.post("Workstation/update", payload)
.then(({ data, status }) => {
if (status === 200) {
resolve(true);
commit("setWorkstation", data.data);
}
})
.catch(({ error }) => {
reject(error);
});
});
}
},
mutations: {
setWorkstation: (state, workstation) => (state.workstation = workstation)
}
};
Error: [vuex] do not mutate vuex store state outside mutation handlers.
API schema
{
"success": true,
"data": [
{
"recordId": 0,
"worksite": 0,
"hStations": [
{
"recordId": 0,
"podId": 0,
"stationOrder": 0,
"workstations": [
{
"recordId": 0,
"name": "string",
"closed": true,
}
]
}
]
}
]
}
How do I fire the change on the close property within the mutation? Thanks in advance
Instead of passing a new object to the action, pass the whole workstation object.
this.updateWorkstation(workstation);
You'll create the posting object, postdata, inside the action, and you'll commit a second mutation for toggling when the promise resolves:
updateWorkstation: ({ commit }, workstation) => {
const postdata = {
recordId: workstation.recordId,
closed: workstation.closed
}
return new Promise((resolve, reject) => {
axiosInstance
.post("Workstation/update", postdata)
.then(({ data, status }) => {
if (status === 200) {
resolve(true);
commit("setWorkstation", data.data);
commit("toggleOldWorkstation", workstation);
}
})
.catch(({ error }) => {
reject(error);
});
});
}
Since the workstation is in the action this way, you're able to call that second mutation to toggle the closed property:
mutations: {
...
toggleOldWorkstation(workstation){
workstation.closed = !workstation.closed;
}
}

Updating the component when data changes (vuejs)

I have a CRUD component and the add user (userRegister) is giving me problems. I am able to successfully add a user, however the view doesn't refresh and the new user doesn't show unless I refresh the page.
Here's the method fired on the Submit button in my Vue Component
onSubmit() {
if (this.password === this.confirmpassword) {
this.$store
.dispatch("users/userRegister", {
operatorNumber: this.operatorNumber,
operatorName: this.operatorName,
password: this.password,
roles: this.operatorRole
})
.then(({ status }) => {
UIkit.offcanvas("#newEmployee").hide();
})
.catch(error => {
console.log("Error: ", error);
});
}
this.resetForm();
},
and my store
import { axiosInstance } from "boot/axios";
export default {
namespaced: true,
state: {
operators: []
},
getters: {
operators: state => {
return state.operators;
}
},
actions: {
async userRegister({ commit }, payload) {
return new Promise((resolve, reject) => {
axiosInstance
.post("user/create", payload)
.then(({ data, status }) => {
if (status === 200) {
resolve(true);
commit("addUser", payload);
}
})
.catch(error => {
reject(error);
console.log("Error: ", error);
});
});
},
},
mutations: {
addUser: (state, operators) => state.operators.splice(state.operators.length, 0, operators)
}
};
What am I missing? Thanks

how to make multiple api request using axios

i am having exsiting service to make api call through axios in my react app,which i think is limited to one api request at a time,i wanted to make multiple request using axios.all,but i am not able to find way to modify the service,see below is the code
As in Action.js you can see that i combine two request which is wrong i guess so,please help me how to combine two request using axios.all,and please suggest api service implementation is correct or what can i do to improve it
APIService.js
import axios from 'axios';
import apiConfig from './apiConfig';
import UserSession from './userSession';
import history from '../utils/history/history';
const session = sessionStorage;
var axiosConfig = axios.create({
baseURL: apiConfig.baseUrl,
headers: {
Authorization: sessionStorage.getItem('token') != null ?
`Bearer ${sessionStorage.getItem('token')}` : null,
Accept: 'application/json',
'Content-Type': 'application/json'
},
timeout: 20000,
responseType: 'json'
});
axiosConfig.interceptors.request.use((config) => {
config.headers.Authorization =
sessionStorage.getItem('token') != null ? `Bearer
${sessionStorage.getItem('token')}` : null;
return config;
},(error) => Promise.reject(error));
const apiService = function(options) {
const onSuccess = function(response) {
if (response.status === 201) {
return Promise.resolve(
Object.assign(
{},
{
message: response.statusText
}
)
);
} else if (response.status === 200) {
if ((response.data && response.data !== null) || response.data !==
undefined || response.data !== '') {
return response.data;
} else {
return Promise.resolve(
Object.assign(
{},
{
message: response.statusText
}
)
);
}
} else if (response.data.length < 1) {
return Promise.reject(
Object.assign(
{},
{
message: 'No Data'
}
)
);
} else {
return response.data;
}
};
const onError = function(error) {
if (error.response) {
if (error.response.status === 401) {
sessionStorage.removeItem('token');
window.location = '/login';
return Promise.reject(error.response);
} else if (error.response.status === 404) {
return Promise.reject(
Object.assign(
{},
{
message: error.response.statusText
}
)
);
} else if (error.response.status === 500) {
return Promise.reject(
Object.assign(
{},
{
message: error.response.statusText
}
)
);
} else {
return Promise.reject(error.response.data);
}
} else if (error.request) {
// The request was made but no response was received
return Promise.reject(
Object.assign(
{},
{
message: error.message
}
)
);
//return Promise.reject(error.message);
} else {
// Something else happened while setting up the request
// triggered the error
return Promise.reject(
Object.assign(
{},
{
message: error.message
}
)
);
}
};
return axiosConfig(options).then(onSuccess).catch(onError);
};
export default apiService;
Request.js
import apiService from '../apiService';
export const FirstRequest = () => {
return apiService({
url: 'FirstURL',
method: 'get',
});
};
export const SecondRequest = () => {
return apiService({
url: 'SecondURL',
method: 'get',
});
};
Action.js
export const SomeHandler = () => (dispatch) => {
dispatch({
type: API_REQUEST
});
FirstRequest()
.then((res) => {
dispatch({
type: API_SUCCESS
});
SecondRequest().then((res) => {
dispatch({
type: API_SUCCESS
});
dispatch({ type: VIEW1, payload: res });
dispatch({ type: VIEW2, payload: res });
}).catch((err) => {
dispatch({
type: API_FAILURE,
payload: err
});
});
})
.catch((err) => {
dispatch({
type: API_FAILURE,
payload: err
});
});
};
This is not related to axios at all. You can combine two async functions together in an action method, using async library:
async.parallel([
getUsers,
getComments
],
function(err, results) {
// the results array will equal to [[], {'x': 'y'}] even though
// the second function had a shorter timeout.
// dispatch here
});
function getUsers(callback) {
callback(null, [])
}
function getComments(callback) {
callback(null, {'x': 'y'})
}
First off, not sure you want to do this in your componentWillMount, because your component will not render until all this is done, it's better to have it in componentDidMount and have some default states that will update once done with these requests. Second, you want to limit the number of setStates you write because they might cause additional re-renders, here is a solution using async/await:
async componentDidMount() {
const firstRequest = await axios.get(URL1);
const secondRequest = await axios.get(URL2);
const thirdRequest = await axios.get(URL3);
this.setState({
p1Location: firstRequest.data,
p2Location: SecondRequest.data,
p3Location: thirdRequest.data,
});
}
i'm working this way. you can use this
const token_config = {
headers: {
'Authorization': `Bearer ${process.env.JWD_TOKEN}`
}
}
const [ res1, res2 ] = await Axios.all([
Axios.get(`https://api-1`, token_config),
Axios.get(`https://api-2`, token_config)
]);
res.json({
info: {
"res_1": res1,
"res_2": res2
}
});

Promise.all() resolves immediately

I'm trying to take some action after upload completion of multiple images, using Promise.all.
However, the code after then runs before the code being dispatched.
What am I confusing here?
submit_all_images({ dispatch, rootState }) {
const imageFileArray = rootState.imageStore.imageFileArray
var promiseArray = []
for ( var imageFile of imageFileArray ) {
promiseArray.push(dispatch('get_signed_request', imageFile))
}
Promise.all(promiseArray)
.then(results => {
console.log("finished with results: " + results)
return dispatch('submit_entire_form')
});
},
get_signed_request ({ dispatch, commit, state }, imgFile) {
const requestObject = {imageName: imgFile.name, imageType: `${imgFile.type}`}
axios.post('http://localhost:3000/sign-s3', requestObject)
.then(response => {
if (response.body.signedRequest && response.body.awsImageUrl) {
const signedRequest = response.body.signedRequest
const awsImageUrl = response.body.awsImageUrl
dispatch('upload_file', { imgFile, signedRequest, awsImageUrl })
} else {
alert('Could not get signed URL.');
}
}, error => {
console.log("ERROR: " + error)
})
},
upload_file ({ dispatch, commit, state}, { imgFile, signedRequest, awsImageUrl }) {
axios.put(signedRequest, imgFile, {
headers: {'Content-Type': imgFile.type}
}).then(response => {
console.log('finished uploading file: ' + imgFile.name )
commit(types.UPDATE_LICENSE_IMG_URLS, awsImageUrl)
}, error => {
alert("fail")
console.log(error)
})
},
I'm not entirely sure, since I have no experience with vuex, but I guess you're missing a few return statements.
get_signed_request({ dispatch, commit, state }, imgFile){
const requestObject = {imageName: imgFile.name, imageType: `${imgFile.type}`}
//here
return axios.post('http://localhost:3000/sign-s3', requestObject)
.then(response => {
if (response.body.signedRequest && response.body.awsImageUrl) {
const signedRequest = response.body.signedRequest
const awsImageUrl = response.body.awsImageUrl
//here
return dispatch('upload_file', { imgFile, signedRequest, awsImageUrl })
} else {
alert('Could not get signed URL.');
}
}, error => {
console.log("ERROR: " + error)
})
},
upload_file({ dispatch, commit, state}, { imgFile, signedRequest, awsImageUrl }){
//here
return axios.put(signedRequest, imgFile, {
headers: {'Content-Type': imgFile.type}
}).then(response => {
console.log('finished uploading file: ' + imgFile.name )
//and here
return commit(types.UPDATE_LICENSE_IMG_URLS, awsImageUrl)
}, error => {
alert("fail")
console.log(error)
})
},
So that get_signed_request returns a Promise that resolves only after axios.post().then() is done, wich depends on first resolving dispatch('upload_file', ...)
And the same for upload_file depending on resolving axios.put().then()depending on commit(types.UPDATE_LICENSE_IMG_URLS, awsImageUrl)

Categories

Resources