Vue CLI Plugin Electron Builder dispatching vuex actions fails - vuejs2

I have a Vue Electron app created with Vue CLI Plugin Electron Builder and I try to integrate vuex, having the following store structure
import Vue from "vue";
import Vuex from "vuex";
import { createPersistedState, createSharedMutations } from "vuex-electron";
import user from "./modules/user";
const debug = process.env.NODE_ENV !== "production";
Vue.use(Vuex);
// eslint-disable-next-line no-console
console.log(user);
export default new Vuex.Store({
modules: {
user
},
plugins: [createPersistedState(), createSharedMutations()],
strict: debug
});
when I try to dispatch actions in App.vue
created() {
const userInDb = UserCotroller.getUser();
this.$store.disptach("setUser", userInDb);
}
I get
"TypeError: this.$store.disptach is not a function"
How do I use vuex in this setup?

you have a typo there:
created() {
const userInDb = UserCotroller.getUser();
this.$store.disptach("setUser", userInDb);
}
change this to:
created() {
const userInDb = UserCotroller.getUser();
this.$store.dispatch("setUser", userInDb);
}
you wrote disptach instead of the correct one dispatch

Related

Vuex 4 Modules can't use global axios property

I have a Vue3 (without Typescript) app running Vuex 4.0.0.
I'm trying to set up a simple GET request in one of my store modules using axios, however I'm getting a Cannot read property of 'get' of undefined when I try to do it via an action called in one of my components, however if I call this.$axios from the component it works fine. For some reason, my modules can't use this.$axios, while elsewhere in the app I can.
I've declared $axios as a globalProperty in my main.js file.
// main.js
import { createApp } from "vue";
import App from "./App.vue";
import { router } from "./router";
import { store } from "./store";
import axios from "axios";
const app = createApp(App).use(store).use(router);
app.config.globalProperties.$axios = axios;
app.mount("#app");
And the store module looks like this (simplified for the purposes of this question):
// store/modules/example.js
const state = () => ({
message: ""
});
const mutations = {
getMessage(state, payload) {
state.message = payload;
}
};
const actions = {
async setMessage(commit) {
this.$axios.get("example.com/endpoint").then(response => {
commit("setMessage", response.message);
});
}
};
export default {
namespaced: true,
state,
getters,
actions,
mutations
};
The main store/index.js that's getting imported in main.js above looks like this:
// store/index.js
import "es6-promise";
import { createStore } from "vuex";
import example from "./modules/example";
export const store = createStore({ modules: { example } });
In the component, I have the following:
// MyComponent.vue
import { mapGetters, mapActions } from "vuex";
export default {
computed: {
...mapGetters({
message: "example/getMessage"
})
},
methods: {
...mapActions({
getMessage: "example/setMessage"
})
}
};
And a simple button with #click="getMessage". Clicking this button, however, returns Uncaught (in promise) TypeError: Cannot read property 'get' of undefined, but if I copy/paste the setMessage action into a component method, it works just fine.
Is there a way for me to expose this.$axios to the store files?
While this is not the ideal solution, as I would've preferred to have my $axios instance available globally with a single declaration in the mount file, it's probably the next best thing.
I made a lib/axiosConfig.js file that exports an axios instance with some custom axios options, and I just import that one instance in every module that needs it.
import axios from "axios";
axios.defaults.baseURL= import.meta.env.DEV ? "http://localhost:8000": "example.com";
axios.defaults.headers.common["Authorization"] = "Bearer " + localStorage.getItem("token");
axios.defaults.headers.common["Content-Type"] = "application/json";
// etc...
export const $axios = axios.create();
And in whatever module I need $axios in, I just import { $axios } from "./lib/axiosConfig. It's not perfect as I mentioned, since I do still have to import it in every module, but it's close enough as far as I can see, and has the added benefit of using the same axios config everywhere by just importing this file.

How to access router from nuxtjs store?

I tried this but only got an error message
This relative module was not found:
* ./router in ./store/index.js
// Ran with yarn dev
import router from './router'
export const state = () => ({
authenticated: false,
})
export const mutations = {
toggleLogin(state, loginStatus, path) {
state.authenticated = loginStatus
if (loginStatus) {
router.push(path)
} else {
router.push('login')
}
},
}
My store path is store/index.js
Vuex mutations and getters doesn't have access to the Vue context. Only actions does.
Also, you can't import the Nuxt router like that. What's that file you're trying to import?
I'd suggest to make an action instead:
export const actions: {
toggleLogin({ commit }, payload) {
this.app.router.push('') //exists
}
}

Vuex-persistedstate does not work after refreshing a page

I am making a spa app with laravel and vue, and I would like to keep my login information in vuex's state after refreshing a page.
I typed
sudo npm install vuex-persistedstate
and installed Vuex-persistedstate and set the plugins as below.
import Vue from 'vue' import Vuex from 'vuex'
import auth from './auth'
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
auth,
plugins: [createPersistedState()],
}
})
export default store
I expected my data to be kept after refreshing a page but it was not.
I checked what is going on, and it seems the plugin object was empty.
it seems that I cannot import the plugins for some reason, but I do not know why.
Could someone help me, please?
my module file
const state = {
user: null,
salonId: null
}
const getters = {
check: state => !! state.user,
checkSalonId: state => {return state.salonId},
}
const mutations = {
setUser (state, user) {
state.user = user
},
setSalonId (state, salonId) {
state.salonId = salonId
}
}
const actions = {
async currentUser (context) {
const response = await axios.get('/api/user')
const user = response.data || null
context.commit('setUser', user)
},
async logout (context) {
context.commit('setUser', null)
context.commit('setSalonId', null)
},
async currentSalon (context, salonId) {
context.commit('setSalonId', salonId)
}
}
export default {
namespaced: true,
state,
getters,
mutations,
actions,
}
You placed plugins in the wrong place. plugins should be inline with modules, not inside modules.
Please take a look at this differences.
const store = new Vuex.Store({
modules: {
auth,
plugins: [createPersistedState()]
}
})
VS
const store = new Vuex.Store({
modules: {
auth
},
plugins: [createPersistedState()]
})
I think you need to setup an option object with the modules you wanna persist. In this example i'm persisting the user module from my store (haven't include the import code)
const persistedStateOptions = {
paths: [
'user',
]
}
export default new Vuex.Store({
modules: {
user,
},
plugins: [createPersistedState(persistedStateOptions)]
})
Look at difference in paths.This worked for me.
import createPersistedState from 'vuex-persistedstate';
Vue.use(Vuex);
export default new Vuex.Store({
strict:true,
modules:{
party,
contract
},
plugins: [createPersistedState(
{
paths:['party.selectedParty']
}
)],
});
Where party is the module name and selectedParty is the name of module state.
Now this plugin only taking care of selectedParty state.
The vue components that get data via state from DB should be kept out of this plugin.

vuex unknown action type when attempting to dispatch action from vuejs component

I'm using laravel, vue and vuex in another project with almost identical code and it's working great. I'm trying to adapt what I've done there to this project, using that code as boilerplate but I keep getting the error:
[vuex] unknown action type: panels/GET_PANEL
I have an index.js in the store directory which then imports namespaced store modules, to keep things tidy:
import Vue from "vue";
import Vuex from "vuex";
var axios = require("axios");
import users from "./users";
import subscriptions from "./subscriptions";
import blocks from "./blocks";
import panels from "./panels";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
},
actions: {
},
mutations: {
},
modules: {
users,
subscriptions,
blocks,
panels
}
})
panels.js:
const state = {
panel: []
}
const getters = {
}
const actions = {
GET_PANEL : async ({ state, commit }, panel_id) => {
let { data } = await axios.get('/api/panel/'+panel_id)
commit('SET_PANEL', data)
}
}
const mutations = {
SET_PANEL (state, panel) {
state.panel = panel
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
Below is the script section from my vue component:
<script>
import { mapState, mapActions } from "vuex";
export default {
data () {
return {
}
},
mounted() {
this.$store.dispatch('panels/GET_PANEL', 6)
},
computed:
mapState({
panel: state => state.panels.panel
}),
methods: {
...mapActions([
"panels/GET_PANEL"
])
}
}
</script>
And here is the relevant code from my app.js:
import Vue from 'vue';
import Vuex from 'vuex'
import store from './store';
Vue.use(Vuex)
const app = new Vue({
store: store,
}).$mount('#bsrwrap')
UPDATE:: I've tried to just log the initial state from vuex and I get: Error in mounted hook: "ReferenceError: panel is not defined. I tried creating another, very basic components using another module store, no luck there either. I checked my vuex version, 3.1.0, the latest. Seems to be something in the app.js or store, since the problem persists across multiple modules.
Once you have namespaced module use the following mapping:
...mapActions("panels", ["GET_PANEL"])
Where first argument is module's namespace and second is array of actions to map.

Lazy loading on vuex modules

I’m trying to use lazy loading with my vuex modules like this article : https://alexjoverm.github.io/2017/07/16/Lazy-load-in-Vue-using-Webpack-s-code-splitting/
Here is my old store\index.js :
import Vue from 'vue';
import Vuex from 'vuex';
import app from './modules/app';
import search from './modules/search';
import identity from './modules/identity';
import profil from './modules/profil';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
app,
search,
identity,
profil,
},
});
I tried to do this :
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store();
import('./modules/app').then((appModule) => {
store.registerModule('app', appModule);
});
import('./modules/search').then((searchModule) => {
store.registerModule('search', searchModule);
});
import('./modules/identity').then((identityModule) => {
store.registerModule('identity', identityModule);
});
import('./modules/profil').then((profilModule) => {
store.registerModule('profil', profilModule);
});
export default store;
But now I have a lot of error like “TypeError: _vm.consultList is undefined", consultList is a mapState variable, I also have same errors on my mapActions
Did I’ve done something wrong ?
All of those modules will be registered when app is loaded any because you most likely add the store to your initial vue instance. How I dynamically loading my vuex module is via the router:
{
path: "/orders/active",
name: "active-orders",
component: ActiveOrders,
props: true,
beforeEnter: (to, from, next) => {
importOrdersState().then(() => {
next();
});
}
},
Then also inside my router file I added:
const importOrdersState = () =>
import("#/store/orders").then(({ orders }) => {
if (!store.state.orders) store.registerModule("orders", orders);
else return;
});