Computed and Maximum call stack size exceeded - vue.js

I have component with computed:
computed: {
pages() {
return Math.ceil(this.$store.state.filter.totalParts / 18);
}
},
In parent i have axios with request:
clearTimeout(this.filteredCategoriesTimer);
this.filteredCategoriesTimer = setTimeout(() => {
axios.get('/shop', {
params: {
page: 1,
per_page: 18,
part_category_tags: this.checkedCategories
}
}).then((response) => {
this.$store.commit(
'addTotalParts',
response.data.totalParts
);
})
}, 0);
and store:
addTotalParts(state, payload) {
state.totalParts = payload;
},
I got error with Maximum call stack size exceeded.
What i need to change for correct error?

Related

Unable to call v-show and #click on same button with vue.js

I'm trying to display text on button based on data variable and call a function for vue.js axios method. I'm able to show text on button based on data variable but unable to call axios post method .I'm getting below error. When I click the button, url "http://localhost:8085/#/applicationtab/3" changes to http://localhost:8085/?#/applicationtab/3.
<span v-if="user.user_role_id ==results.desk_user_role_id">
<button small color="primary" style="width:400px;" #click="forward" v-show="forwardTo">{{ forwardTo }}</button><br>
<button small color="primary" style="width:400px;" #click="revert" v-show="revertTo">{{ revertTo }}</button>
</span>
data() {
return {
user: [],
roles: {
2: { name: 'Registration', next: 4, previous: 0 },
4: { name: 'Technical', next: 6, previous: 2 },
6: { name: 'Executive', next: 0, previous: 4 },
},
};
},
mounted() {
const currentuserUrl = 'api/profile';
VueAxios.get(currentuserUrl, {
headers: {
'X-Requested-With': 'XMLHttpRequest',
Authorization: `Bearer ${localStorage.getItem('token')}`,
},
}, {
timeout: 100000,
})
.then((response) => {
// debugger;
this.user = response.data;
// console.log(response.data);
// debugger;
});
computed: {
forwardTo() {
const { next } = this.roles[this.user.user_role_id];
return next ? `Forward to ${this.roles[next].name}` : false;
},
revertTo() {
const { previous } = this.roles[this.user.user_role_id];
return previous ? `Revert to ${this.roles[previous].name}` : false;
},
},
methods: {
forward() {
this.$refs.form.forward();
const url = `/api/registration/${this.$route.params.id}/forward`;
VueAxios.post(url, this.forward_message, {
headers: {
'X-Requested-With': 'XMLHttpRequest',
Authorization: `Bearer ${window.localStorage.getItem('token')}`,
},
}, {
timeout: 10000,
})
.then((response) => {
if (response.status === 200) {
// this.successmessage = 'Forwarded successfully.';
this.message = 'Forwarded successfully.';
}
})
.catch((error) => {
console.log(error);
});
},
revert() {
const url = `/api/registration/${this.$route.params.id}/revert`;
VueAxios.post(url, this.forward_message, {
headers: {
'X-Requested-With': 'XMLHttpRequest',
Authorization: `Bearer ${window.localStorage.getItem('token')}`,
},
}, {
timeout: 10000,
})
.then((response) => {
if (response.status === 200) {
// this.successmessage = 'Forwarded successfully.';
this.message = 'Reverted successfully.';
}
})
.catch((error) => {
console.log(error);
});
},
computed: {
forwardTo() {
const { next } = this.roles[this.user.user_role_id];
return next ? `Forward to ${this.roles[next].name}` : false;
},
Error is ocurring because of this part I think. this.roles[next]
I can't find roles property on your properties(data and computed)
Is this a prop from parent component?
You need to check if the roles property or props and its child property next exist.
this.user is an array or object? If it is an array containing an single object then, you must try this.user[0].user_role_id, or if it is an object so there may be a user id which is not present as a key in the roles object.
For that you can use this in your computed property.
forwardTo() {
const tempObj = this.roles[this.user.user_role_id];
return tempObj ? `Forward to ${this.roles[tempObj.next].name}` : false;
}

Can't get the state in Vuex getters and mutations after page reload

I'm using vue-cli#3 and vuex#3.0.1.
First step: I open the URL and the website is working. Second step: I refresh the website, then errors are thrown. So I can't get the data in store's getters by mapActions and I can't use the methods which I import by mapActions. Even if I can't access my data which is mounted on the Vue instance.
In vue-devtools, the state keeps being loaded when I got in trouble, as seen here. I've also tried vue-cli#2 to run the same code, again without success, so I've assumed that Vuex is the cause.
Store code:
import Vue from 'vue'
import Vuex from 'vuex'
import util from '../lib/util'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
locale: localStorage.getItem('locale') || 'en',
langdrop: false,
loading: false,
langs: ['en', 'zh'],
modal: {
notice: false,
rule: false,
about: false
},
phonelink: false,
bet: 1,
myinfo: {
star: 0,
amount: 0,
staticEarn: 0,
staticEarnd: 0,
inviteEarn: 0,
inviteEarnd: 0
},
bonusPot: 0,
myInviteCode: 0,
inviteCode: util.getParams().code || 0
},
getters: {
myinfo: state => state.myinfo,
langdrop (state) {
return state ? state.langdrop : false
},
loading (state) {
return state ? state.loading : false
},
langs (state) {
return state.langs.filter(item => {
return item !== state.locale
})
},
locale (state) {
return state.locale
},
notice (state) {
return state.modal.notice
},
rule (state) {
return state.modal.rule
},
about (state) {
return state.modal.about
},
phonelink (state) {
return state.phonelink
},
bet (state) {
return state.bet
},
myInviteCode (state) {
return state.myInviteCode
},
inviteCode (state) {
return state.inviteCode
},
bonusPot (state) {
return state.bonusPot
}
},
actions: {
toggleLang (context) {
context.commit('ToggleLang')
},
setlocale (context, lang) {
localStorage.setItem('locale', lang)
context.commit('SetLocale', lang)
},
UpdateHubLoading (context) {
context.commit('UpdateHubLoading')
},
settingModal (context, type) {
context.commit('SettingModal', type)
},
togglePhoneLink (context) {
context.commit('TogglePhoneLink')
},
setBetValue (context, value) {
if (value > 30 || value < 1) {
return
}
value = Math.floor(value)
context.commit('SetBetValue', value)
},
setMyinfo (context, value) {
let target = {}
target.addr = value.addr
context.commit('SetMyinfo', target)
},
setMyInviteCode (context, code) {
context.commit('SetMyInviteCode', code)
},
setBonusPot (context, bonus) {
context.commit('SetBonusPot', util.bigNumbertoNumber(bonus, 18, 4))
}
},
mutations: {
ToggleLang (state) {
state.langdrop = !state.langdrop
if (state.langdrop === true) {
state.pendingdrop = false
}
},
SetLocale (state, lang) {
state.locale = lang
},
UpdateHubLoading (state) {
state.loading = !state.loading
},
SettingModal (state, type) {
let status = !state.modal[type]
if (status === true) {
state.modal = {
notice: false,
rule: false,
about: false
}
}
state.modal[type] = status
},
TogglePhoneLink (state) {
state.phonelink = !state.phonelink
},
SetBetValue (state, value) {
state.bet = value > 30 ? 30 : value
},
SetMyinfo (state, value) {
if (state) {
state.myinfo = value || {
star: 0,
amount: 0,
staticEarn: 0,
staticEarnd: 0,
inviteEarn: 0,
inviteEarnd: 0
}
}
},
SetMyInviteCode (state, code) {
state.myInviteCode = code || 0
},
SetBonusPot (state, bonus) {
state.bonusPot = bonus || 0
}
}
})
Components Code:
created () {
this.getMyinfo()
},
methods: {
...mapActions(['setMyinfo', 'setBonusPot', 'setAddress']),
getMyinfo () {
if (!this.address) return
this.hasAddr = true
this.$Contract.methods.addrPly(this.address).call().then(res => {
this.setMyinfo(res)
})
},
getBonus () {
if (this.$Contract) {
this.$Contract.methods.bonusPot().call().then(res => {
this.setBonusPot(res)
})
}
}
}

Vuex update state by using store actions

I have two functions in my store, one that gets data by calling API and one that toggles change on cell "approved". Everything working fine, except that when I toggle this change it happens in database and I get the response that it is done but It doesn't update on UI.
I am confused, what should I do after toggling change to reflect change on UI, should I call my API from .then or should I call action method responsible for getting data from server.
export default {
state: {
drivers: {
allDrivers:[],
driversError:null
},
isLoading: false,
token: localStorage.getItem('token'),
driverApproved: null,
driverNotApproved: null
},
getters: {
driversAreLoading (state) {
return state.isLoading;
},
driverError (state) {
return state.drivers.driversError;
},
getAllDrivers(state){
return state.drivers.allDrivers
}
},
mutations: {
getAllDrivers (state) {
state.isLoading=true;
state.drivers.driversError=null;
},
allDriversAvailable(state,payload){
state.isLoading=false;
state.drivers.allDrivers=payload;
},
allDriversNotAvailable(state,payload){
state.isLoading=false;
state.drivers.driversError=payload;
},
toggleDriverApproval(state){
state.isLoading = true;
},
driverApprovalCompleted(state){
state.isLoading = false;
state.driverApproved = true;
},
driverApprovalError(state){
state.isLoading = false;
state.driverError = true;
}
},
actions: {
allDrivers (context) {
context.commit("getAllDrivers")
return new Promise((res,rej)=>{
http.get('/api/admin/getAllDrivers').then(
response=>{
if (response.data.success){
let data=response.data.data;
data=data.map(function (driver) {
return {
/* response */
};
});
context.commit("allDriversAvailable",data);
res();
}else {
context.commit("allDriversNotAvailable",response.data)
rej()
}
})
.catch(error=>{
context.commit("allDriversNotAvailable",error.data)
rej()
});
});
},
toggleDriverApproval (context, payload){
return new Promise((res, rej)=>{
http.post("/api/admin/toggleDriverApproval",{
driver_id: payload
})
.then( response => {
context.commit('driverApprovalCompleted');
res();
}).catch( error =>{
context.commit('driverApprovalError');
rej()
})
})
}
}
}
and here is the code on the view, I wrote the necessary code for better clarification of the problem
export default {
name: 'Drivers',
data: () => ({
data: [],
allDrivers: [],
driversErrors: []
}),
created() {
this.$store
.dispatch('allDrivers')
.then(() => {
this.data = this.$store.getters.getAllDrivers
})
.catch(() => {
this.errors = this.$store.getters.driverError
})
},
computed: {
isLoading() {
return this.$store.getters.driversAreLoading
}
},
methods: {
verify: function(row) {
console.log(row)
this.$store.dispatch('toggleDriverApproval', row.id).then(() => {
this.data = this.$store.getters.getAllDrivers
console.log('done dis')
})
},
},
}
if I understand your issue, you want the UI displaying your data to change to the updated data after making a post request.
If you are using Vuex you will want to commit a mutation, and use a getter display the data.
I am not sure how your post request is being handled on the server but if successful typically you would send a response back to your front end with the updated data, and commit a mutation with the updated data.
Example:
Make a Post request
toggleDriverApproval (context, payload){
return new Promise((res, rej)=>{
http.post("/api/admin/toggleDriverApproval",{
driver_id: payload
})
.then( response => {
context.commit('driverApprovalCompleted', response.data);
res();
}).catch( error =>{
context.commit('driverApprovalError', error.response.data);
rej()
})
})
}
If succesful commit the mutation
.then( response => {
context.commit('driverApprovalCompleted', response.data);
res();
})
response.data being your data you want to mutate the state with.
Mutation Example:
customMutation(state, data) {
state.driverApproval = data
}
Getter Example:
driver(state) {
return state.driverApproval
}
displaying the getter in a template
<template>
<div v-if="driver">{{driver}}</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
name: Example,
computed: {
driver() {
return this.$store.getters.driver
},
// or use mapGetters
...mapGetters(['driver'])
}
}
</script>
more examples can be found at Vuex Docs

function not defined upon requesting via axios in vue

I am trying to make an axios call and it works fine but when I call the function from the scope it returns me
loadData is undefined.
import vSelect from 'vue-select';
export default {
props : [],
data : () => {
return {
assets : [],
folders : [],
parent_id : 0,
moveParentId : null,
selectedAsset: {},
parentStack : [],
searchTerm : '',
};
},
components: {
vSelect,
},
created() {
this.loadData(this.parent_id);
this.createFolder();
},
methods : {
loadData(parentId) {
axios
.get(
'/api/assets',
{
params: {
parent_id: parentId,
},
},
)
.then((response) => {
this.parentStack.push(parentId);
this.assets = response.data;
})
.catch((error) => {
if (error.response.status === vue.$options.HTTP_STATUS.UNPROCESSABLE_ENTITY) {
}
});
},
createFolder() {
$('#create-folder-button').on('click', function (e) {
let form = $('#create-folder').find('form'),
namefield = form.find('input#name'),
name = namefield.val(),
action = '/assets',
errorelem = form.find('#create-error');
axios
.post(action, {
name: name,
type: 1,
})
.then(() => {
$('#create-folder').modal('hide');
loadData(this.parent_id); //ERROR OCCURS HERE.
}, function (error) {
if (error.response != null) {
if (error.response.status == vue.$options.HTTP_STATUS.UNPROCESSABLE_ENTITY) {
errorelem.html(error.response.status).show();
}
}
});
});
}
this is my code.

pass computed property as method parameter?

So I have a store with values:
export const store = new Vuex.Store({
state: {
selectedGradeId: null,
},
getters:{
selectedGradeId: state => {
return state.selectedGradeId
},
},
mutations:{
SET_SELECTED_GRADE_ID(state, gradeid){
state.selectedGradeId = gradeid
},
CLEAR_SELECTED_GRADE_ID(state){
state.selectedGradeId = null
},
},
actions:{
loadStudentsForGrade (gradeId) {
return new Promise((resolve, reject) => {
axios.get('/students/'+gradeId)
.then((response)=>{
... do stuff
resolve(response)
}, response => {
reject(response)
})
})
},
}
})
and inside my component i basically have a select that loads the student list for the particular grade:
<select id="grades" name="grades" v-model="selectedGradeId" #change="loadStudentsForGrade(selectedGradeId)"
methods: {
loadStudentsForGrade(gradeId) {
this.$store.dispatch('loadStudentsForGrade', {gradeId})
.then(response => {
}, error => {
})
},
},
computed: {
selectedGradeId: {
get: function () {
return this.$store.getters.selectedGradeId;
},
set: function (gradeId) {
this.$store.commit('SET_SELECTED_GRADE_ID', gradeId);
}
},
}
when the 'loadStudentsForGrade' method is called in my component, it takes 'selectedGradeId' as a parameter, which is a computed property.
Now the problem I have is that inside my store, the action 'loadStudentsForGrade' gets an object( i guess computed?) instead of just the gradeid
object i get is printed to console:
{dispatch: ƒ, commit: ƒ, getters: {…}, state: {…}, rootGetters: {…}, …}
The first parameter of your action is the store, and the second the payload.
so you should do :
actions:{
// here: loadStudentsForGrade (store, payload) {
loadStudentsForGrade ({ commit }, { gradeId }) {
return new Promise((resolve, reject) => {
axios.get('/students/'+gradeId)
.then((response)=>{
//... do stuff
//... commit('', response);
resolve(response)
}, response => {
//... commit('', response);
reject(response)
})
})
},
}
Related page in the docs :
https://vuex.vuejs.org/en/actions.html#dispatching-actions