global store plugin error with vue 3 condition - vue.js

With vue 3, I have state actions in different files globally, but they do not perform the necessary checks in the vue connector. I don't understand where I am doing wrong. I will be happy if you help.
I am waiting for your help to see the mistakes I have made. I am open to any comments.
app.js
require('./bootstrap');
import {createApp} from 'vue';
import App from './App.vue'
import WebsiteRouter from './Website/router';
import AdminRouter from './Admin/router';
import ApplicationRouter from './Application/router';
import store from './store';
axios.defaults.withCredentials = true;
store.dispatch('getUser').then(() => {
createApp(App)
.use(chanceRoute())
.use(store)
.use(DashboardPlugin)
.mount("#app");
})
import { createStore } from 'vuex'
import app from './app'
import appConfig from './app-config'
export default new createStore({
modules: {
app,
appConfig,
}
})
app\index.js
import axios from 'axios';
import sharedMutations from 'vuex-shared-mutations';
export default {
state: {
user: null
},
getters: {
user(state) {
return state.user;
},
verified(state) {
if (state.user) return state.user.email_verified_at
return null
},
id(state) {
if (state.user) return state.user.id
return null
}
},
mutations: {
setUser(state, payload) {
state.user = payload;
}
},
actions: {
async login({dispatch}, payload) {
try {
await axios.get('/sanctum/csrf-cookie');
await axios.post('/api/login', payload).then((res) => {
return dispatch('getUser');
}).catch((err) => {
throw err.response
});
} catch (e) {
throw e
}
},
async register({dispatch}, payload) {
try {
await axios.post('/api/register', payload).then((res) => {
return dispatch('login', {'email': payload.email, 'password': payload.password})
}).catch((err) => {
throw(err.response)
})
} catch (e) {
throw (e)
}
},
async logout({commit}) {
await axios.post('/api/logout').then((res) => {
commit('setUser', null);
}).catch((err) => {
})
},
async getUser({commit}) {
await axios.get('/api/user').then((res) => {
commit('setUser', res.data);
}).catch((err) => {
})
},
async profile({commit}, payload) {
await axios.patch('/api/profile', payload).then((res) => {
commit('setUser', res.data.user);
}).catch((err) => {
throw err.response
})
},
async password({commit}, payload) {
await axios.patch('/api/password', payload).then((res) => {
}).catch((err) => {
throw err.response
})
},
async verifyResend({dispatch}, payload) {
let res = await axios.post('/api/verify-resend', payload)
if (res.status != 200) throw res
return res
},
async verifyEmail({dispatch}, payload) {
let res = await axios.post('/api/verify-email/' + payload.id + '/' + payload.hash)
if (res.status != 200) throw res
dispatch('getUser')
return res
},
},
plugins: [sharedMutations({predicate: ['setUser']})],
}
app-config\index.js
import { $themeConfig } from '../../themeConfig'
export default {
namespaced: true,
state: {
layout: {
isRTL: $themeConfig.layout.isRTL,
skin: localStorage.getItem('skin') || $themeConfig.layout.skin,
routerTransition: $themeConfig.layout.routerTransition,
type: $themeConfig.layout.type,
contentWidth: $themeConfig.layout.contentWidth,
menu: {
hidden: $themeConfig.layout.menu.hidden,
},
navbar: {
type: $themeConfig.layout.navbar.type,
backgroundColor: $themeConfig.layout.navbar.backgroundColor,
},
footer: {
type: $themeConfig.layout.footer.type,
},
},
},
getters: {},
mutations: {
TOGGLE_RTL(state) {
state.layout.isRTL = !state.layout.isRTL
document.documentElement.setAttribute('dir', state.layout.isRTL ? 'rtl' : 'ltr')
},
UPDATE_SKIN(state, skin) {
state.layout.skin = skin
// Update value in localStorage
localStorage.setItem('skin', skin)
// Update DOM for dark-layout
if (skin === 'dark') document.body.classList.add('dark-layout')
else if (document.body.className.match('dark-layout')) document.body.classList.remove('dark-layout')
},
UPDATE_ROUTER_TRANSITION(state, val) {
state.layout.routerTransition = val
},
UPDATE_LAYOUT_TYPE(state, val) {
state.layout.type = val
},
UPDATE_CONTENT_WIDTH(state, val) {
state.layout.contentWidth = val
},
UPDATE_NAV_MENU_HIDDEN(state, val) {
state.layout.menu.hidden = val
},
UPDATE_NAVBAR_CONFIG(state, obj) {
Object.assign(state.layout.navbar, obj)
},
UPDATE_FOOTER_CONFIG(state, obj) {
Object.assign(state.layout.footer, obj)
},
},
actions: {},
}

Related

Vuex is not mutating the state

I am trying to switch authenticated from false to true, a property in the state, It's not working.
My codes from store.js
state() {
return{
authenticated : false,
user : {}
}
},
getters : {
authenticated(state){
return state.authenticated
}
},
mutations : {
set_authenticated(state, value){
return state.authenticated = value
}
},
My updated code from login.vue (script)
data() {
return {
allerrors : [],
success : false,
data: {
email : "",
password : ""
}
}
},
methods : {
login: function() {
this.$store
.dispatch("login", this.data)
.then(response => {
this.allerrors = [],
this.success = true,
this.data = {}
alert(response.data)
})
.catch((error) => {
this.allerrors = error.response.data.error
this.success = false
alert(allerrors)
})
},
My updated action is :
async login({ commit }, data) {
await axios.post('login', data)
.then(response => {
commit('set_authenticated',true);
})
.catch((error) => {
this.allerrors = error.response.data.error
this.success = false
})
}
There are a few problems here:
First, if that is the full code for your store.js file, then you are missing the call to createStore() (for Vue 3) or new Vuex.Store() (for Vue 2)
import { createStore } from 'vuex'
// Create a new store instance.
const store = createStore({
state () {
return {
count: 0
}
},
mutations: {
increment (state) {
state.count++
}
}
})
Source
The second problem is that you shouldn't be committing mutations from your Single File Components. The typical flow is:
Components dispatch actions
Actions commit mutations
Mutations update state
You're trying to commit a mutation directly from the component.
You need to add an action to your store.js
async login({ commit }, userData) {
await axios.post('login', userData)
.then(response => {
commit('set_authenticated',true);
})
.catch((error) => {
this.allerrors = error.response.data.error
this.success = false
})
}
Mutation:
mutations : {
set_authenticated(state, value){
state.authenticated = value
}
},
Then your Login.vue would change to something like:
methods: {
login: function() {
this.$store
.dispatch("login", { userData })
.then(() => )) // whatever you want to do here.
.catch(err => console.error(err));
}
}
mutations shouldn't have a return statement. it should be like this
mutations : {
set_authenticated(state, value){
state.authenticated = value
}
},

Unknown action type in Nuxt Vuex store

I have a problem calling the action from vuex. Everytime I try to access the loginUser action I get an error 'unknown action type' from vuex. maybe I'm not calling it the right way. Please tell me what's wrong with my code.
store: user.js
import axios from 'axios'
export const state = () => ({
users: [],
loggedIn: false,
})
export const getters = {
getLoggedIn: (state) => { return state.loggedIn },
}
export const actions = {
loginUser({ commit }, payload){
if(state.loggedIn){
console.log("you're already logged in!")
}else{
return new Promise(async(resolve, reject) => {
const { data } = await axios.post('/api/users/login-admin', {
login: payload.login,
password: payload.password
})
if(data.success){
commit("loggedIn", true)
resolve()
}else{
commit("loggedIn", false)
reject('an error has ocurred')
}
return data.success
}).catch(err => alert(errCodes(err.code)))
}
},
}
export const mutations = {
setLoggedIn(state, payload) {
state.loggedIn = payload
}
}
login.vue
computed: {
...mapGetters(['getCount'] , {user: 'getLoggedIn'}),
...mapActions([
'loginUser'
]),
},
methods: {
onSubmit: function(){
this.$store.dispatch({
type: 'loginUser',
email: this.login,
pass: this.pass
}).then(()=>{
this.$router.push('../admin_2065')
this.onReset()
}).catch(e => console.log(e))
},
onReset(){
this.login = ''
this.pass = ''
this.$nextTick().then(() => {
this.ready = true
})
}
},
error:
any help will be appreciated, thanks.
mapActions should be inside the methods option and add the namespace user/ :
computed: {
...mapGetters(['getCount'] , {user: 'getLoggedIn'}),
},
methods: {
...mapActions([
'user/loginUser'
]),
onSubmit: function(){
this['user/loginUser']({
email: this.login,
pass: this.pass
}).then(()=>{
this.$router.push('../admin_2065')
this.onReset()
}).catch(e => console.log(e))
},
onReset(){
this.login = ''
this.pass = ''
this.$nextTick().then(() => {
this.ready = true
})
}
},

How to keep user logged in between page refreshes in FastAPI and Vue

I am new to vue.js, I have a simple web application(Vue frontend connected to a FastAPI backend) that a user can create an account and login, All of this works so far but when I refresh the page the user is logged out.
And console show an error:
Uncaught (in promise) TypeError: Cannot read property '$store' of undefined
What am I doing wrong? How to keep user logged in even after page refresh. Can anyone please help me?? thanks
store/index.js
import Vuex from 'vuex';
import Vue from 'vue';
import createPersistedState from "vuex-persistedstate";
import auth from './modules/auth';
// Load Vuex
Vue.use(Vuex);
// Create store
const store = new Vuex.Store({
modules: {
auth
},
plugins: [createPersistedState()]
});
export default store
store/modules/auth.js
import { postUserLogInAPI } from "../../service/apis.js";
const state = {
token: "",
expiration: Date.now(),
username: ""
};
const getters = {
getToken: (state) => state.token,
getUsername: (state) => state.username,
getFullname: (state) => state.fullname,
isAuthenticated: (state) => state.token.length > 0 && state.expiration > Date.now()
};
const actions = {
async LogIn({ commit }, model) {
await postUserLogInAPI(model).then(function (response) {
if (response.status == 200) {
commit("LogIn", response.data)
}
})
},
async LogOut({ commit }) {
commit('LogOut')
}
};
const mutations = {
LogIn(state, data) {
state.username = data.username
state.fullname = data.fullname
state.token = data.token
state.expiration = new Date(data.expiration)
},
LogOut(state) {
state.username = ""
state.fullname = ""
state.token = ""
state.expiration = Date.now();
},
};
export default {
state,
getters,
actions,
mutations
};
service/http.js
import axios from 'axios'
import { Loading, Message } from 'element-ui'
import router from '../router/index.js'
import store from '../store';
let loading
function startLoading() {
loading = Loading.service({
lock: true,
text: 'Loading....',
background: 'rgba(0, 0, 0, 0.7)'
})
}
function endLoading() {
loading.close()
}
axios.defaults.withCredentials = true
axios.defaults.baseURL = 'http://0.0.0.0:80/';
axios.interceptors.request.use(
(confing) => {
startLoading()
if (store.getters.isAuthenticated) {
confing.headers.Authorization = "Bearer " + store.getters.getToken
}
return confing
},
(error) => {
return Promise.reject(error)
}
)
axios.interceptors.response.use(
(response) => {
endLoading()
return response
},
(error) => {
Message.error(error.response.data)
endLoading()
const { status } = error.response
if (status === 401) {
Message.error('Please Login')
this.$store.dispatch('LogOut')
router.push('/login')
}
return Promise.reject(error)
}
)
export default axios
components/NavBar.vue
<script>
export default {
name: "NavBar",
computed: {
isLoggedIn: function () {
return this.$store.getters.isAuthenticated;
},
username: function () {
return this.$store.getters.getUsername;
},
fullname: function () {
return this.$store.getters.getFullname;
},
},
methods: {
async logout() {
await this.$store.dispatch("LogOut");
this.$router.push("/login");
},
},
};
</script>

Vue and Vuex: Can't dispatch an action in a state service

I'm trying to dispatch an action in a service. Here's the vue code
import { mapActions} from "vuex";
methods: {
...mapActions("user", ["updateUseEmailAction"]),
onSubmit() {
this.submitted = true;
this.$v.$touch();
this.$v.$error ? "" : this.updateUser();
},
updateUser() {
console.log("test");
this.updateUseEmailAction({
form: this.form,
});
},
},
user.js
import userService from "#/services/userService";
export const state = {
loading:false,
};
export const actions = {
updateUserNameAction({ commit }, params) {
return new Promise(() => {
userService
.updateUserName(params)
.then((data) => {
this._vm.$toast.success(data.message);
})
.catch((err) => {
this._vm.$toast.error(err.data.message);
});
});
},
updateUserEmailAction({ commit }, params) {
console.log("inside user/updateUserEmailAction");
return new Promise(() => {
userService
.updateUserEmail(params)
.then((data) => {
this._vm.$toast.success(data.message);
})
.catch((err) => {
this._vm.$toast.error(err.data.message);
});
});
},
};
I get "test" in the log but I get this error
unknown local action type: updateUseEmailAction, global type: user/updateUseEmailAction
Why does it look for a local action or function named updateUseEmailAction and not dispatch it from user service? How to fix this?

how can i use async and await in action object in vuex?

I'm gonna use an API and take it off some information, I use async/ await in mutations but as you know it's not standard that we used async data in mutation, and we have to use it in actions but how we can do it?
here my vuex codes:
import axios from "axios";
const state = {
token: "hjOa0PgKqC7zm86P10F3BQkTuLsEV4wh",
posts: [],
pending: true,
error: false,
}
const mutations = {
async getDataFromApi(state) {
try {
const res = await axios.get(
`https://api.nytimes.com/svc/movies/v2/reviews/picks.json?api-key=${state.token}`
);
if (res.status == 200) {
state.posts = res.data;
state.error = false;
}
} catch (e) {
state.posts = null;
state.error = e;
}
state.pending = false;
},
};
const actions = {
showData({
commit
}) {
commit("getDataFromApi");
},
}
and here vuejs codes that I used in the component :
<script>
import { mapState } from "vuex";
export default {
name: "Home",
mounted() {
this.getDataFromApi();
},
computed: {
...mapState(["pending", "error", "posts"]),
},
methods: {
getDataFromApi() {
this.$store.dispatch("showData");
},
},
};
</script>
It works perfectly in mutation but for standards, how can use this in action instead of mutation?
Well, actually it is pretty similar to what you have done so far :
const mutations = {
getDataFromApi(state, data) {
state.posts = data;
state.error = false;
state.pending = false;
},
setError(state, error) {
state.error = error;
state.posts = null;
state.pending = false;
},
};
const actions = {
async showData({ commit }) {
try {
const res = await axios.get(
`https://api.nytimes.com/svc/movies/v2/reviews/picks.json?api-key=${state.token}`
);
if (res.status == 200) {
commit("getDataFromApi", res.data);
} else {
commit("setError", new Error("Something went wrong."));
}
} catch (e) {
commit("setError", e);
}
},
};