Vuex: importing a single state from an object - vue.js

I have a simple store:
UsersStore.js
state() {
return {
users: {
name: '',
userHasPermissions: false,
}
}
}
I am trying to use mapState to have the state accessible in my component. When I import the entire User object of the store like below, it works:
App.vue
computed: {
...mapState('users', {
myUser: 'user'
}
but I just want to import the userHasPermissions state but when I do the following, it does not seem to work:
App.vue
computed: {
...mapState('users', {
hasPerms: 'user.hasPermissions'
}

You can use vuex getters to get a specific property from any store object
state() {
return {
users: {
name: '',
userHasPermissions: false,
}
}
},
getters: {
userHasPermission(state) {
return state.users.userHasPermission || false;
}
}
Now you can use mapGetters to map store getters to your vue component
computed: {
...mapGetters({
hasPerms: "userHasPermission"
})
}
If you want to avoid using mapGetters and getters and use mapState, then you need to define a computed function inside your mapState to fetch the desired property
computed: {
...mapState({
hasPerms: (state) => state.users.userHasPermission
})
}

Related

How to use a Nuxt component to pass a parameter to a vuex getter method? (while maintaining three dot notation)

GOAL: I would like to watch a vuex state object (MATCH_DATA) for changes, specific to the value of a prop (topicId). So, I would like to set the watcher to watch MATCH_DATA[topicId]. And whenever MATCH_DATA[topicId] updates, I'd like to call a function (in this early case just logging it).
However, since MATCH_DATA is a getter how would I pass a parameter to it? The vuex getter does not seem to be designed to take in parameters. I have seen some examples by explicitly calling this.$store.state.etc.etc. but is there a way to do this while retaining the three dot notation I currently have?
Or, is there some better way of achieving this goal that does not involve a vuex getter?
Current Code:
Nuxt component:
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
props: ['topicId'],
computed: {
...mapGetters('sessionStorage', ['MATCH_DATA']),
},
watch: {
MATCH_DATA (newMatchData, oldMatchData) {
console.log(newMatchData);
}
},
mounted() {
this.SUBSCRIBE_TO_TOPIC(this.topicId);
},
methods: {
...mapActions('sessionStorage', ['SUBSCRIBE_TO_TOPIC'])
}
}
vuex store:
/* State */
export const state = () => ({
MATCHES: {},
});
/* GETTERS */
export const getters = {
MATCH_DATA: (state) => {
return state.MATCHES;
},
};
Your getter can simply return a function like this:
export const getters = {
MATCH_DATA: (state) => {
return topicId => {
// return something
}}
},
};
Then you can create a computed property to access those getter:
export default {
computed: {
...mapGetters('sessionStorage', ['MATCH_DATA']),
yourComputedProperty () {
return this.MATCH_DATA(this.topicId)
}
}
}
Then you can watch the computed property to react on changes.
watch: {
yourComputedProperty (newData, oldData) {
console.log(newData);
}
}

How to get value of Vuex getter inside of Vue local data object

Hey this seemed to be pretty simple, but I just can't figure out how to get my loggedInUser object to work outside the template. I read through a bunch of other answers and I know I have to do something to store the getter in a local data object.
I have a temporary 'id' object set up because that's what I ultimately want to set to loggedInUser.id in order to attach to my Axios request.
Here's the page I want to make changes on:
<script>
import { mapGetters } from 'vuex'
// import vuex from 'vuex'
export default {
data: () => ({
results: "",
id: "15",
}),
computed: {
...mapGetters(['loggedInUser'])
},
// var id = {{loggedInUser}};
methods: {
getData() {
this.$axios.get('http://127.0.0.1:8000/api/v1/actors/',
{params: {user: this.id} }
)
.then(response => {this.results = response.data});
}
}
}
</script>
and here's my index.js for store:
export const getters = {
isAuthenticated(state) {
return state.auth.loggedIn
},
loggedInUser(state) {
return state.auth.user
}
}
The mapGetters helper simply maps store getters to local computed
properties
This:
computed: {
...mapGetters(['loggedInUser'])
},
Is equivalent to this:
computed: {
loggedInUser() {
return this.$store.getters.loggedInUser
},
},
Replace this.id with this.loggedInUser.id in your axios request, and get rid of the temporary id data property.
getData() {
this.$axios.get('http://127.0.0.1:8000/api/v1/actors/', {
params: {
user: this.loggedInUser.id
}
})
.then(response => {
this.results = response.data
});
}
We are assuming getData only gets called when the user is authenticated. If that's not the case, have in mind this.loggedInUser may be null or undefined and accessing this.loggedInUser.id will throw an error.

How to use this data from Vuex inside the component?

What is the best way to use this data from the Vuex store's Action in the needed component?
import axios from 'axios'
export default {
namespaced: true,
state: {
items: []
},
actions: {
fetchCategories ({state, commit}) {
return axios.get('/api/v1/categories')
.then(res => {
const categories = res.data
commit('setItems', {resource: 'categories', items: categories}, {root: true})
return state.items
})
}
}
}
Component
export default {
components: {
ThreadCreateModal,
ThreadList
},
data () {
return {
...
}
},
computed: {
...
},
created () {
...
},
methods: {
...
}
</script>
Where and how should I use that action for binding the data in this component?
Use mapState by import it from vuex and call it in computed:
computed: {
...mapState(['items']), // if you dont use namespace
...mapState("your_module_name", ['items'] ) // if you use namespace
},
then you can access it by this.items.
However, you can access it directly this.$store.state.items

Vuex mapped state always undefined in component

I have a namespaced Vuex store module, and I am trying to access that module's state in a component (via mapState) to set a default value in my data. However, the "mapped state" is always undefined in my component.
My store is:
cartDetail.js
export const defaults = {
id: null,
items: [],
},
const state = { ...defaults, };
export default {
namespaced: true,
state,
}
and in my component, I have:
<script>
import { mapState, mapActions, } from 'vuex';
data() {
defaultSelected: this.cartDetail.items[0],
},
computed () {
...mapState('cartDetail', ['cartDetail,'],),
setDefaultSelected () {
return this.cartDetail.items[0];
},
},
created () {
this.cartFetch(userId);
}
</script>
Even when I console.log(this.cartDetail); in either my setDefaultSelected computed, or in created hook, it is undefined! Any help would be much appreciated!!
your data section looks incorrect. It should look like this:
data() {
return {
defaultSelected: this.items[0]
}
},
In mapState you should indicate state props (and their module name if they are not from the root state). I assume that carDetail.js is a store module.
computed () {
...mapState({
id: state => state.cartDetail.id,
items: state => state.cartDetail.items
}),
setDefaultSelected () {
return this.items[0];
},
},

Write a Global Methods to check authentication in NuxtJS

I have difficulty to Write a Global Methods to check authentication in NuxtJS. The methods which I can write v-if in components to display if it return True.
I put this code in layout/default.vue but it doesn't works.
/layout/defaut.vue
<script>
import '~/assets/icons'
export default {
head () {
return !this.mobileLayout ? {} : {
bodyAttrs: {
class: 'mobile'
}
}
},
created () {
this.LoggedIn()
},
methods: {
LoggedIn: function () {
return this.$store.state.authUser
}
}
}
</script>
Components:
<template>
<div v-if="LoggedIn">Authenticated</div >
</template>
Error:
Property or method "LoggedIn" is not defined on the instance but referenced during render
Hope you guy help me!
Since authUser is a state property in vuex, not a method. LoggedIn in your component is simply returning a value from the state and does not need to be a method.
You should use a computed instead of a method. You also do not need to call LoggedIn from the created method, once it is a computed, it will be calculated automatically.
<script>
import '~/assets/icons'
export default {
head () {
return !this.mobileLayout ? {} : {
bodyAttrs: {
class: 'mobile'
}
}
},
computed: {
LoggedIn: function () {
return this.$store.state.authUser
}
}
}
</script>
Or even better, use mapState from vuex which is documented here https://vuex.vuejs.org/en/state.html
<script>
import Vuex from 'vuex'
import '~/assets/icons'
export default {
head () {
return !this.mobileLayout ? {} : {
bodyAttrs: {
class: 'mobile'
}
}
},
computed: {
...mapState({
LoggedIn: 'authUser'
})
}
}
</script>
Your template does not need to be changed.