I could not map my vuex actions in a component - vue.js

I'm trying to map my vuex actions (one particularly) but I keep getting the error Property or method "logout" is not defined on the instance but referenced during render.. Here is my component code:
<template>
<header id="header">
<div class="logo">
<router-link to="/">Vue Authenticate</router-link>
</div>
<nav>
<ul>
...
<li v-if="authenticated" #click="logout">
Log Out
</li>
</ul>
</nav>
</header>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
export default {
computed: {
...mapGetters({
authenticated: "isAuthenticated",
}),
},
mathods: {
...mapActions(["logout"]),
},
};
</script>
and here is my store/index.js file:
import Vue from "vue";
import Vuex from "vuex";
import axios from "axios";
import router from "../router/index.js";
Vue.use(Vuex);
export default new Vuex.Store({
actions: {
logout({commit}) {
localStorage.removeItem("idToken");
localStorage.removeItem("userId");
commit("clearData");
router.push("/")
}
},
});
Any idea of where I am missing something? By the way, mapGetters works perfectly fine.
I am using vuex in version 3.4.0.

You are writing "mathods" instead of methods:
methods: {
...mapActions(["logout"]),
},

Related

Vuex: unknown mutation type: dropdownState

im beginner and trying something for learn. im using vue js 2 and have a problem with vuex. When I click div of dropdown, I want to add active class and show content of dropdown. The problem is
unknown mutation type: dropdownState.
store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
active: false,
},
getters: {
isOpen (state) {
return state.active;
},
},
mutation: {
dropdownState (state) {
state.active = !state.active;
console.log('hi');
},
},
});
Dropdown.vue
<template>
<div class="dropdown" #click="dropdownState">
<slot name="button"></slot>
<slot></slot>
</div>
</template>
<script>
import { mapMutations } from 'vuex';
export default {
name: 'Dropdown',
methods: {
...mapMutations(['dropdownState']),
}
};
</script>
DropdownContent.vue
<template>
<div>
<div class="dropdown-content right" :class="{ active : active }"></div>
</div>
</template>
<script>
import { mapState, mapGetters } from 'vuex';
export default {
name: 'DropdownContent',
computed: {
...mapState(['active']),
...mapGetters(['isOpen']),
},
};
</script>
It's supposed to be mutations (with an s)
mutations: {
...
}
https://vuex.vuejs.org/guide/mutations.html#mutations
Btw, it will be actions too!

Vuex- Page is not updating after commit changes made to state

I am trying to make a simple project which has 2 Vue pages add.vue and read.vue. If we add a message in add.vue(using commit to mutate teh state), results should be displayed in read.vue , using Vuex store. (I am using Nuxt)
store/index.js file=>
export const state = () => ({
messages:[]
})
export const mutations={
addMessage:(state, comment)=> {
state.messages.push(comment)
}
}
add.vue file
<template>
<div class="addContainer">
<b-form #submit.prevent="handleSubmit">
<b-form-group id="input-group-2" label="Comment:" label-for="input-2">
<b-form-input
id="input-2"
v-model="comment"
required
placeholder="Enter Your Comment"
></b-form-input>
</b-form-group>
<b-button type="submit" variant="primary">Submit</b-button>
</b-form>
</div>
</template>
<script>
import Header from '~/components/Header'
import {mapActions} from 'vuex'
import {mapState} from 'vuex'
export default {
data() {
return {
comment:''
}
},
computed:{
...mapState([
'messages'
])
},
methods:{
handleSubmit(){
this.$store.commit('addMessage', this.comment)
console.log('Messages is '+this.messages )
this.comment = ''
}
},
components:{
Header
}
}
</script>
read.vue
<template>
<div>
<p>Read Messages</p>
<ul>
<li v-for="(msg, index) in messages" :key="index">
<b>{{ msg}}</b>
<br>
{{ messages}}
</li>
</ul>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
data() {
return {}
},
computed:{
...mapState({
messages:state=>state.messages
})
}
}
</script>
In Vue component , I can see messages array inside state changes after adding a message , but same changes are not reflected in read page.
Add getters to your store:
export const getters= {
getMessages: state => state.messages
}
and then use the getters in your component instead of accessing the state directly:
// read.vue
<script>
import {mapGetters} from 'vuex'
export default {
data() {
return {}
},
computed:{
...mapGetters({
messages: 'getMessages',
})
}
}
</script>

Global check user Logged In - NuxtJS

I config a global check user if LoggedIn or not to rendering components in NuxtJS but I cant do it. Please help me.
I write computed to wrapper components (layouts/default.vue)
~/layouts/default.vue
<template>
<router-view></router-view>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
computed: {
...mapGetters({
LoggedIn: 'authUser'
})
}
}
}
</script>
But I cant use it on children components / pages.
~/pages/index.vue
<template>
<div class="index-page">
<div class="" v-if="LoggedIn">
asdasd
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log(this.LoggedIn)
// Result: Undefined
}
}
</script>

vue component does not update when data is changed external

My component does not update the loaded property when Store.loaded changes:
Component
import { Vue } from 'vue-property-decorator'
import Component from 'nuxt-class-component'
import { Store } from '../repositories'
#Component
export default class Layout extends Vue {
loaded = Store.loaded
}
Store
class Root {
loaded = false
}
export let Store = new Root()
export default Store
In your example Store is just plain function (class), without any reactivity (no Vue watchers attached for Store.loaded field).
Only properties inside component's data are reactive. If you want reactive single store outside of vue components (better for big frontend applications), you should use Vuex
Simple example will be:
App.vue:
<script>
import { mapGetters, mapMutations } from 'vuex';
import store from './store';
import ChildComponent from './components/ChildComponent.vue';
export default {
store,
components: { ChildComponent },
methods: {
...mapMutations(['toggleLoaded']),
},
computed: {
...mapGetters({
isLoaded: 'isLoaded',
}),
}
}
</script>
<template>
<div id="app">
Toggle loaded
<h3>Root component: </h3>
<div>The loaded flag is: {{ isLoaded }}</div>
<ChildComponent />
</div>
</template>
components/ChildComponent.vue:
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters({
isLoaded: 'isLoaded', //accessing to same data, as root through single Vuex state
}),
}
}
</script>
<template>
<div class="hello">
<h3>Child component</h3>
<div>The loaded flag is: {{ isLoaded }}</div>
</div>
</template>
And reactive Vuex store:
store/index.js:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state = {
loaded: false
};
const getters = {
isLoaded: state => state.loaded,
};
const mutations = {
toggleLoaded: (state) => {
state.loaded = !state.loaded;
}
};
export default new Vuex.Store({
state,
mutations,
// actions,
getters,
strict: true
});
You can find full source of this example on GitHub.

Vue.js how to pass params with router-link?

I am trying tp pass an id param when the user click on the link generated by but I don't see it in the html
The id should be the currentUserId set or initialised in store .. so I defined a computed prop and appropriate getter ('getCurrentUserId') which pick up the currentUserId from the state..
Where am I wrong ?
<li id="shoppinglists">Shopping Lists</li>
I should get :
href="#/shoppinglists/1"
App.vue
<template>
<div id="app">
<ul class="navigation">
<li id="home"><router-link :to="{ name: 'Home' }" >Home</router-link></li>
<li id="shoppinglists"><router-link :to="{ name: 'ShoppingLists', params: { id: currentUserId } }" >Shopping Lists</router-link></li>
</ul>
<router-view></router-view>
</div>
</template>
<script>
import store from '#/vuex/store'
import { mapGetters } from 'vuex'
export default {
name: 'app',
computed: {
...mapGetters({ currentUserId: 'getCurrentUserId' })
},
store
}
</script>
vuex/getters.js
import _ from 'underscore'
export default {
getCurrentUserId: state => state.currentUserId,
...
}
vuex/store.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import actions from './actions'
import mutations from './mutations'
Vue.use(Vuex)
const state = {
currentUserId: 1,
...
}
export default new Vuex.Store({
state,
mutations,
getters,
actions
})
Ok got it .. it's not concatenated with the ref url... but using vue web-tools I can see that' the object to: has both the path '/shoppinglists' and params: object {id: 1}... it's not obvious to switch mindset to vue behaviour ...