Why do I get this error:
Error [vuex] Do not mutate vuex store state outside mutation handlers
This happens when I call this component.
<template lang="pug">
.auth-popup
button.auth-popup__button-top.auth-popup__button-top_close(
type='button'
aria-label='Закрыть форму авторизации'
@click='$emit(`close`)'
)
h2.auth-popup__title Вход или регистрация
form.auth-popup__form(@submit.prevent='submitHandler')
input.auth-popup__fake-input(v-show='showFakeInput' aria-hidden='true' autocomplete='off' ref='fakeInput')
label.auth-popup__label(for='authLogin') Телефон
input#authLogin.auth-popup__input(
type='tel'
autocomplete='tel'
v-model='login'
@input='inputHandler'
ref='loginInput'
)
p.auth-popup__error(v-if='login && !isPhoneAuth') Телефон указан неверно
p.auth-popup__error(v-if='error' v-html='error')
p.auth-popup__timer(v-if='getCodeTimer' v-html='codeTimerMessage')
button.auth-popup__button-send(
type='submit'
:disabled='!isLoginLength || !isPhoneAuth || getCodeTimer || showPreloader'
)
span.auth-popup__button-inner(v-if='!showPreloader') Получить код
Preloader.auth-popup__preloader(:show='showPreloader' :color='`#ffffff`')
button.auth-popup__button-email(
type='button'
@click='$emit(`email`)'
) Войти по почте
</template>
<script>
import { mapActions, mapMutations, mapGetters } from 'vuex'
import { REGEXPS } from '~/assets/js/utils/constants/regexps';
import { MESSAGES } from "~/assets/js/utils/constants/messages";
import delay from '~/assets/js/utils/functions/promiseTimeout';
import Preloader from "~/components/modules/Preloader"
export default {
name: 'AuthPhone',
components: {
Preloader
},
data() {
return {
showFakeInput: false,
showPreloader: false,
login: '',
error: ''
}
},
computed: {
isPhoneAuth() {
return REGEXPS.FULL_PHONE_SYMBOLS.test(this.login);
},
isLoginLength() {
const phoneDigits = this.login.trim().replace(/\D/g, ``);
return phoneDigits.length > 9;
},
createPhoneValue() {
let phoneNumber = this.login;
if (phoneNumber.startsWith('8')) {
phoneNumber = '7' phoneNumber.slice(1);
}
return ` ${phoneNumber.replace(/\D /g, '')}`;
},
...mapGetters({
getAuthResponse: 'authorization/getAuthResponse',
getCodeTimer: 'authorization/getCodeTimer',
codeTimerMessage:'authorization/codeTimerMessage'
})
},
methods: {
...mapActions({
authRequest: 'authorization/authRequest'
}),
...mapMutations({
startCodeTimer: 'authorization/startCodeTimer',
resetCodeTimer: 'authorization/resetCodeTimer'
}),
inputHandler() {
this.error = '';
if (this.getCodeTimer) {
this.resetCodeTimer();
}
},
async submitHandler() {
this.showPreloader = true;
const sendData = {
ident_method: `PHONE`,
login: this.createPhoneValue
};
await this.authRequest(sendData)
.then(() => {
this.showPreloader = false;
const data = this.getAuthResponse;
if (data.result) {
if (data.is_registered && !data.is_active) {
this.error = MESSAGES.ERROR.ACCOUNT_DEACTIVATED;
} else if (data.is_code_sended) {
this.startCodeTimer(30);
this.$emit('enter');
}
} else if (MESSAGES.ERROR[data.error]) {
this.error = MESSAGES.ERROR[data.error];
} else {
this.error = data.error;
}
});
},
},
mounted() {
if (this.getAuthResponse.login && this.getAuthResponse.ident_method === `PHONE`) {
this.login = this.getAuthResponse.login;
}
this.showFakeInput = true;
this.$nextTick()
.then(() => {
this.$refs.fakeInput.focus();
return delay(500);
})
.then(() => {
this.$refs.loginInput.focus();
this.showFakeInput = false;
});
},
}
</script>
The problem arises in this mutation - this.startCodeTimer (30);
Mutation file:
export default {
setAuthResponse(state, data) {
state.authResponse = data
},
setCodeResponse(state, data) {
state.codeResponse = data
},
setRegResponse(state, data) {
state.regResponse = data
},
setAuthCode(state, data) {
state.authCode = data
},
startCodeTimer(state, time) {
state.newCodeTimer = time
state.codeTimerId = setInterval(() => {
if (state.newCodeTimer) {
state.newCodeTimer--
} else {
clearInterval(state.codeTimerId)
}
}, 1000)
},
resetCodeTimer(state) {
state.newCodeTimer = 0
}
}
If I understand correctly, then the problem is here.
state.codeTimerId = setInterval(() => {
if (state.newCodeTimer) {
state.newCodeTimer--
} else {
clearInterval(state.codeTimerId)
}
}, 1000)
But so far there are no ideas how to solve it.
CodePudding user response:
The problem was that state cannot be changed inside setInterval. Solution: Create a mutation that will change the state and call this mutation inside setInterval.
Example:
setNewCode(state, count) {
state.newCodeTimer = count
},
startCodeTimer(state, time) {
state.newCodeTimer = time
state.codeTimerId = setInterval(() => {
if (state.newCodeTimer) {
this.commit('authorization/setNewCode', time--)
} else {
clearInterval(state.codeTimerId)
}
}, 1000)
},