Vuex with Nuxt Error: this.$store is undefined - vue.js

I'm coding along with a Nuxt course and I got the following error while of course it worked in the tutorial.
TypeError: can't access property "dispatch", this.$store is undefined
store/index.js file:
import Vuex from "vuex";
const createStore = () => {
return new Vuex.Store({
state: { loadedPosts: [] },
mutations: {
setPosts(state, posts) {
state.loadedPosts = posts;
},
},
actions: {
setPosts(vuexContext, posts) {
vuexContext.commit("setPosts", posts);
},
},
getters: {
loadedPosts(state) {
console.log("imhere");
return state.loadedPosts;
},
},
});
};
export default createStore;
the script in posts/index.vue file:
<script>
export default {
data() {
return {
loadedPosts: [{id: "1",title: "First Post"}],
};
},
created() {
this.$store.dispatch("setPosts", this.loadedPosts);
},
};
</script>

Related

this.$store.dispatch works but ...mapActions does not

Using vue 2 I'm trying to initialize data in vuex from a component before it loads. I can use the this.$store.dispatch and the action, along with its subsequent mutation, will run as expected from the created() function. If I call the same method in the created() function on the component using ...mapActions, the action and mutation in the module in the vuex store do not run as expected. I've looked at various ways to do this with namespacing the module (as it isn't the only module in this program), but I can't seem to get the method to run. It may be a timing in the lifecycle issue, but I'm not sure why created() wouldn't be appropriate. The addStage method is what I'm trying to have run to create the data in vuex to be displayed once the component that needs the data is loaded.
In a separate component (not shown here) I can use the ...mapActions helper by firing it from a button #click and it runs the addStage method from vuex just fine. What am I missing?
Component:
<template>
<div v-for="stage in getFlow.stages" :key="stage.id">
<flowstage v-for="step in stage.steps" :key="step.id">
<flowstep></flowstep>
</flowstage>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'flowbuildersub',
created(){
this.addStage;
//this.$store.dispatch('flowbuilder/addStage');
console.log("added stage");
},
methods: {
...mapActions('flowbuilder', ['addStage']),
},
computed: {
...mapGetters('flowbuilder', ['getFlow']),
}
}
</script>
Store:
import Vue from 'vue';
import Vuex from 'vuex';
import flowbuilder from './modules/flowbuilder.js';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
error: null,
loading: false,
information: null
},
getters: {
getError(state) {
return state.error;
},
getInformation(state) {
return state.information;
},
getLoading(state) {
return state.loading;
},
},
mutations: {
setInformation(state, payload) {
state.information = payload
},
setError(state, payload) {
state.error = payload
},
setLoading(state, payload) {
state.loading = payload
}
},
modules: {
flowbuilder
}
})
flowbuilder.js module:
export const state = {
flow: {
id: Math.ceil(Math.random()*100000000)+Math.floor(Date.now() / 1000),
name: null,
description: null,
modifiedBy: null,
stages: [],
},
};
export const getters = {
getFlow(state) {
return state.flow;
},
getStages(state) {
return state.flow.stages;
},
};
export const actions = {
addStage({ commit }) {
let defaultStep = {
id: 1,
type: "Assign",
data: null,
description: null,
subStep: null,
required: null,
selected: true,
};
let defaultStage = {
id: 1,
label: null,
description: null,
selected: false,
steps: [
defaultStep
],
};
console.log("made it here");
commit('ADDSTAGE', defaultStage);
},
};
export const mutations = {
ADDSTAGE(state, defaultStage) {
state.flow.stages.push(defaultStage);
console.log("added stage");
},
};
export default {
namespaced: true,
state,
getters,
actions,
mutations
};

Vue redirect after getting store's values

I was trying to make an edit page /edit/:id where input's value comes from the vuex store, but if the store doesn't have a task with the same id of the params I want to redirect to /404, how can I achieve this? tried created() but it didn't work. Im using Vue3
<script>
export default {
name: "EditTaskForm",
data() {
return {
newTaskDesc: "",
};
},
created() {
const task = this.$store.getters.getTaskById(Number(this.$route.params.id));
if (!task) this.$router.push("/404");
},
mounted() {
const task = this.$store.getters.getTaskById(Number(this.$route.params.id));
this.newTaskDesc = task.desc;
},
methods: {
submitEdit() {
this.$store.dispatch("editTask", {
newTaskDesc: this.newTaskDesc,
id: Number(this.$route.params.id),
});
this.$router.push("/");
},
},
};
</script>
Try follwoing:
beforeRouteEnter(to, from, next) {
const task = this.$store.getters.getTaskById(Number(this.$route.params.id));
if (!task) this.$router.push("/404");
},
<script>
export default {
name: "EditTaskForm",
data() { ... },
mounted() { ... },
methods: { ... },
beforeRouteEnter(to, from, next) {
const task = this.$store.getters.getTaskById(Number(this.$route.params.id));
if (!task) this.$router.push("/404");
}
};
</script>
Navigation Guards

Vuex mapActions: mapper parameter must be either an Array or an Object

When I'm trying to use the "getProducts" method through mapActions i am getting the "this.getProducts" is not a function.
Basically i get the actions from my product.js. So i don't know really why the error is existing.
I hope u can help me to handle with it. :)
My component ProductList.vue:
<script>
import ProductCard from "./ProductCard.vue";
import { mapState, mapActions } from "vuex";
export default {
components: {
ProductCard
},
computed: {
//state.modulname.state.js(products state)
...mapState("product" ["products"])
},
mounted() {
this.getProducts();
},
methods: {
...mapActions("product"["getProducts"])
}
};
</script>
<style>
</style>
My product.js File:
import store from "../../store/store";
import Product from "../../apis/Product";
const state = {
product: null,
products: [],
};
const mutations = {
SET_PRODUCT(state, product) {
state.product = product;
},
SET_PRODUCTS(state, products) {
state.products = products;
},
};
const actions = {
getProduct({ commit }, productId) {
Product.show(productId).then((response) => {
commit("SET_PRODUCT", response.data);
});
},
getProducts({ commit }) {
Product.all().then((response) => {
commit("SET_PRODUCTS", response.data);
});
},
};
const getters = {
getProductID() {
return (id) => state.products.filter((product) => product.id === id);
},
};
export default {
namespaced: true,
store,
state,
mutations,
actions,
getters,
};
Try this:
...mapActions([
'product/getProducts'
])

Vuejs with namespaced modules and unknow mutation type

i have created two store modules and I did the import into main store.
When I load my drawer view, I am getting the next error.
What am I doing wrong here
error:vuex.esm.js [vuex] unknown mutation type: SET_DRAWER
//Drawer.vue
.........
computed: {
...mapState("navstore", ["barColor", "barImage"]),
drawer: {
get() {
return this.$store.state.navstore.drawer;
},
set(val) {
this.$store.commit("SET_DRAWER", val);
},
},
computedItems() {
return null;
//this.items.map(this.mapItem);
},
profile() {
return {
avatar: true,
title: "Gestan",
};
},
},
methods: {},
.........
.........
//store/index.js
import Vue from "vue";
import Vuex from "vuex";
import { default as auth } from ".auth";
import { default as navstore } from "./navStore";
Vue.use(Vuex);
export default new Vuex.Store({
modules: { auth: auth, navstore: navstore },
});
//navstore.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const SET_BAR_IMAGE = "NAVSTORE/SET_BAR_IMAGE";
const SET_DRAWER = "NAVSTORE/SET_DRAWER";
export default {
namespaced: true,
state: {
barColor: "rgba(0, 0, 0, .8), rgba(0, 0, 0, .8)",
barImage:
"https://demos.creative-tim.com/material-dashboard/assets/img/sidebar-1.jpg",
drawer: null,
},
mutations: {
[SET_BAR_IMAGE](state, payload) {
state.barImage = payload;
},
[SET_DRAWER](state, payload) {
state.drawer = payload;
},
},
actions: {
actionSetDrawer({ commit }, payload) {
commit(SET_DRAWER, payload);
},
},
};
//auth.js
import Vue from "vue";
import Vuex from "vuex";
import * as storage from "#/store/storage";
import services from "#/services/api/AuthenticationService";
Vue.use(Vuex);
const SET_USER = "AUTH/SET_USER";
const SET_TOKEN = "AUTH/SET_TOKEN";
export default {
namespaced: true,
state: {
token: null,
user: null,
isUserLoggedIn: false,
},
mutations: {
[SET_TOKEN](state, token) {
state.token = token;
state.isUserLoggedIn = !!token;
},
[SET_USER](state, user) {
state.user = user;
},
},
getters: {
isAuthenticated: (state) => !!state.token,
// authStatus: state => state.status
},
actions: {
actionDoLogin({ dispatch }, payload) {
return services.login(payload).then((res) => {
dispatch("actionSetUser", res.data.user);
dispatch("actionSetToken", res.data.token);
});
},
};
You need to remove prefixes with slash from mutation names because your modules namespaced and you will always access this mutations outside indicating a module name like this moduleName/mutation.
For instance:
const SET_BAR_IMAGE = "NAVSTORE/SET_BAR_IMAGE";
const SET_DRAWER = "NAVSTORE/SET_DRAWER";
// should be
const SET_BAR_IMAGE = "SET_BAR_IMAGE";
const SET_DRAWER = "SET_DRAWER";
Because the SET_DRAWER mutation is inside a navspaces module you should call it indicating a module name:
this.$store.commit("navstore/SET_DRAWER", val);
Don't try to call actions inside actions like this:
actionDoLogin({ dispatch }, payload) {
return services.login(payload).then((res) => {
dispatch("actionSetUser", res.data.user);
dispatch("actionSetToken", res.data.token);
});
},
Use mutations in a desired combination:
actionDoLogin({ dispatch }, payload) {
return services.login(payload).then((res) => {
commit(SET_USER, res.data.user);
commit(SET_TOKEN, res.data.token);
});
},

How to load data before create VueJS app?

I'm a little confused. How to load data (main.js file) and afrer (inside a component) set this data to data() function (calc.js)?
I have the data.json file:
{
"store_data": "VUE_STORE",
}
I have the store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
url_server: 'data.json',
store_data: '',
},
actions: {
getServerData({commit}){
return new Promise((resolve, reject) => {
Vue.http.get(this.state.url_server).then(function (response) {
if (response.status == "200") {
commit('LOAD_SERVER_DATA', response)
resolve()
}
});
});
}
},
mutations: {
LOAD_SERVER_DATA (state, response) {
this.store_data = response.data.store_data;
},
},
});
I have the main.js file:
import Vue from 'vue';
import VueResource from 'vue-resource';
import { store } from './store/store';
Vue.config.productionTip = false;
import calc from './components/calc/calc';
Vue.use(VueResource);
var app = new Vue({
el: '#app',
store,
data: {},
components: {
'calc': calc,
},
beforeCreate() {
this.$store.dispatch('getServerData');
}
});
And the component file calc.js
module.exports = {
name: 'calc',
template: `
<div>
<h1>calc</h1>
<h2>{{test_value}}</h2>
</div>
`,
data() {
return {
test_value: 'AAA',
}
},
methods: {
updateTimer() {
},
},
created() {
this.test_value = this.$store.state.store_data;
/* this.$store.dispatch('getServerData').then(() => {
this.test_value = this.$store.state.store_data;
console.log(this.$store.state.store_data);
});*/
},
computed: {
},
mounted() {
},
};
I'd like to set a test_value in calc.js file value this.$store.state.store_data. How it is possible?
Don't use data for data owned by the store. Use computed to return the store value, like so
created() {
this.$store.dispatch('getServerData');
},
computed: {
test_value(){
return this.$store.state.store_data;
}
},
mounted() {
},
And then in the vuex store the mutation has a little bug
mutations: {
LOAD_SERVER_DATA (state, response) {
state.store_data = response.data.store_data;
},