Vue.js Vuex cannot access store in router - vue.js

I've seen that this question have been asked a couple of time but I cannot find any good answer and don't understand why my code is behaving like this.
As said in the title I'm trying to import my store in the router to be able to use my getters on conditional and grant a user to access or not a route.
But as soon as i'm trying to import the store I get the following error:
[vuex] unknown action type: autoSignIn
this is coming from:
const vm = new Vue({
router,
store,
provide,
i18n,
render: handle => handle(App),
created () {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
this.$store.dispatch('autoSignIn', user)
this.$store.dispatch('loadMatter')
this.$store.dispatch('loadFootprints')
this.$store.dispatch('loadMembers')
}
})
So I guess that when my app is starting the store hasn't loaded yet.
How can I workaround that I want to be able to use
store.getters.mygetter
Thank you very much

I think you need to import your store in your router file
I'm doing it like this:
import store from "#/store/index.js";

Are you using modules of vuex?
Can you share your store index file?
https://vuex.vuejs.org/guide/modules.html
If you are using modules of vuex, you should do this.$store.dispatch('module_name/action_name')

I have my store split into files
Vue.use(Vuex);
const store = new Vuex.Store({
state,
actions,
mutations,
getters,
plugins: [
process.env.NODE_ENV === 'development' && createLogger({ collapsed: false }),
].filter(Boolean),
});
export default store;

Related

Using Vuex State in main js

I am trying to use my store state in main.js but it vanishes my component, can I use state in mian.js
Axios.defaults.headers.common['BranchId'] = this.$store.state.myBrachId,
if not what how can I set the default headers dynamically then..?
You're asking how to access a Vuex store outside a Vue component. The syntax that you're currently using is only valid if you're writing a Vue component.
In case you want to access Vuex outside (any .js file) you should, first, export the store. Then, import that store in your file and finally use the store as you place.
Let's see an example:
store/index.js
export const store = new Vuex.Store({
state () {
myBrachId: 'niceBranch007'
}
});
Then, in any other .js file (main.js in your case)
import { store } from 'store/index.js'
console.log(store.state.myBrachId)
If you're trying to add headers to axios I'd ask you to consider if you should really be getting that header data from a Vuex store anyways. Remember that any browser refresh will clear your store so you should not rely on it's availability more than you need to. Using localStorage or sessionStorage might be better for what you're looking to do here.
I am doing this right now this is my store
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
branchId: "",
},
getters:{
},
mutations: {
},
actions: {},
modules: {}
});
In header cmponent
this.$store.state.branchId = this.Branches[index].branchId;
in main js
import Axios from 'axios'
import { store } from './store/index'
Axios.defaults.headers.common['BranchId'] = store.state.branchId;
this is not setting axios header, it comes empty

How to change the vuex-persist key option dynamically?

I am using the plugin: https://www.npmjs.com/package/vuex-persist, and it works great. But I am not sure that what I am trying to do will work.
My application has a module of authentication, and the user can create their own settings that are stored in vuex and localstorage. But since there will be different users there will be different settings and that is why each user will have different localStorage, that is why they need to have different name.
In that case I need to change the name of the key setting on the storage plugin dynamically, and I don't know how to do that. The setting for the plugin look like this
import Vue from 'vue'
import App from 'App.vue';
import Vuex 'vuex';
import VuexPersist from 'vuex-persist';
Vue.use(Vuex);
const vuexLocalStorage = new VuexPersist({
key: 'vuex' // I WANT TO CHANGE THIS DYNAMICALLY, how to do that?
storage: window.localStorage, // or window.sessionStorage or localForage
// Function that passes the state and returns the state with only the objects you want to store.
// reducer: state => state,
// Function that passes a mutation and lets you decide if it should update the state in localStorage.
// filter: mutation => (true)
})
const store = new Vuex.Store({
...
plugins: [vuexLocalStorage.plugin]
});
...
new Vue({
store,
el: '#app',
render: h => h(App)
});

TypeError: Converting circular structure to JSON Vuejs

I am getting the error
"TypeError: Converting circular structure to JSON"
while using vuex-persistedstate plugin.
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex.Store({
// ...
plugins: [createPersistedState()]
})
I had found some solution to use plugin with no error as below
plugins: [createPersistedState]
But it is not saving the state details.
You haven't mentioned where you want to store the data. Since I am storing vuex data in localStorage my code goes something like:
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex.Store({
// ...
plugins: [createPersistedState(
storage: window.localStorage
)]
})
So basically, just pass storage: window.localStorage to your createPersistedState() method.
Enjoy!

How can I break my Vuex actions into multiple files and still use `dispatch`?

I have broken my actions into multiple files to make my project more maintainable and extensible. Trying to dispatch from one action to another, however, is not working.
My file tree looks like this:
store.js
actions
|--actions.js
|--createShape.js
|--addShape.js
My store.js looks like:
import actions from './actions/actions'
const PlaypadStore = {
namespaced: true,
state: {
localState: ''
},
actions: {
...actions,
},
}
My actions.js folder has the following:
import CREATE_SHAPE from './createShape';
import ADD_SHAPE from './addShape';
export default {
CREATE_SHAPE,
ADD_SHAPE,
}
The problem is trying to dispatch ADD_SHAPE from CREATE_SHAPE. My createShape.js looks like the following:
const CREATE_SHAPE = ({ state, dispatch }) => {
return dispatch('ADD_SHAPE')
}
export default CREATE_SHAPE;
But it returns me this:
[vuex] unknown local action type
The question is this: how can I break my actions into multiple files, but still be able to dispatch actions from one to another?
if you use 'export default...' in your action-files and import your files in the store like that:
import actions_one from './actions_one';
import actions_two from './actions_two';
you can then use the spread operator to make it like you're importing one object:
export default new Vuex.Store({
namespaced: true,
actions: {
...actions_one,
...actions_two
},
...
you need to let Vuex know that actions.js, createShape.jsand addShape.jsare "modules" of your store for this to work.
You can read more about it in the Vuex Modules documentation.
Basically you need an index.js file declaring the modules at the root of your store. That should look like this:
import actions from "./actions";
import createShape from "./createShape";
import addShape from "./addShape";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
actions,
createShape,
addShape
}
});
At this point your dispatch call should work, UNLESS it comes from another vuex store module, in that case just specify "root = true" as they pointed out here.

Vuex module not accessible from rootState

I needed to get route's query parameters inside Vuex in order to preload filter settings and update the state of the application. To make this possible I installed vuex-router-sync.
Next step was to synchronize the Vuex and VueRouter.
Router:
Vue.use(VueRouter);
export default new VueRouter({ mode: 'history' });
Store:
Vue.use(Vuex);
export default new Vuex.Store({
modules: { filters: FiltersModule },
plugins: [ FiltersPlugin ]
});
App's bootstrap:
const unsync = sync(store, router);
new Vue({
el: '#restaurant-admin-app',
components: {
'App': AppComponent,
'filters': FilterComponent,
'orders-table': OrdersTableComponent
},
store,
router
});
My FilterPlugin that should trigger the URL parsing:
export default store => {
store.dispatch('filters/parseURLFilterSettings');
}
And now, the funny part, here's the URL parsing action:
parseURLFilterSettings: ({ state, commit, rootState }) {
console.log('RootState:', rootState);
console.log('Route module (incorrect):', rootState.route);
console.log('Filters module (correct):', rootState.filters);
console.log('Object\'s keys:', Object.keys(rootState));
}
What am I doing wrong? I thought it might be something with syncing, but at the end the console.log shows clearly that the route Object is there (and it's not empty), but somehow when I access it, it's undefined. Thank you in advance.
The problem was very well explained here. What it basically says is that the object's value is evaluated when you open it's body in the console.
The problem was I didn't have the route module loaded yet, because I was trying to dispatch an action from a vuex plugin which seems to load before the vuex-router-sync's syncing was done.
The problem was solved when I moved application's bootstrap logic from vuex plugins into the AppRootComponent's mount lifecycle event.
You should import the router-sync. After that your store and routes wil behave properly. I usually do this in the main.js file.
import router from './router'
import store from './store'
import { sync } from 'vuex-router-sync'
sync(store, router)