I have a store module called store/auth.js in that I have a getter
export const getters = {
isAuthenticated(state) {
return state.token != null
}
}
Now I want to call this namespaced getter in my middleware. How would I go about calling that getter?
This seems to work but even without namespacing anything ...
export default function (context) {
if(!context.store.getters.isAuthenticated)
context.redirect('/')
}
}
Do the getters behave differently than an action or mutation where I have to call auth/?
context.store.dispatch("auth/SomeVuexAction")
You can access vuex getters as below:
context.store.getters["modulename/gettername"]
i.e.(In your case) mention correct module and getter name
context.store.getters["auth/isAuthenticated"]
Related
I defined a vuex getter function with parameter like this:
const getters = {
getProjectById: (state) => (id) => {
return state.projects.find(project => project.id === id)
}
}
Now, i want to use this getter in my component, but i couldn't find a way to pass the parameter to the getter.
Here is my getter hook computed property:
computed: {
...mapGetters(["currentUserPhoto","getProjectById"])
},
Is it possible to pass Id parameter which is come from router, to "getProjectId" getter? If is possible, what is the best way to do it?
Add another computed property called projectById which takes the route param as parameter and returns the project :
computed: {
...mapGetters(["currentUserPhoto","getProjectById"]),
projectById(){
return this.getProjectById(this.$route.params.id)
}
},
I am using Vuex for state right now and taking advantage of getters to acquire state so that I don't have to use props. However, I am curious if I can use Vuex to replace this type of function emitting. How would that be done with Vuex, if it's even possible.
Parent
<child-component #handleselectproduct="selectProduct"></child-component>
selectProduct: function() {
axios.get()
}
Child
<button #click="selectProduct></button>
selectProduct: function() {
this.$emit('handleselectproductselection');
}
You could use vuex actions and mutations. Mutations are used for synchronous and actions for asynchronous calls. You could imagine them as setters as opposed to getters that you already use. So in your current example, you would call an action which may or may not set a state property through a mutation. you would define this action with:
const store = new Vuex.Store({
state: {
selectedProduct: {}
},
getters: {
getSelectedProduct: state => {
return state.selectedProduct
}
},
mutations: {
selectProduct(state, payload) {
state.selectedProduct = payload
}
},
actions: {
async selectProduct(context, axios) {
const { commit } = context
const product = await axios.get(...) // some call
commit('selectProduct', product)
}
}
})
After defining these, you can call the action through the this.$store.dispatch('selectProduct', axios) method in the child component and have your result available in the parent component or wherever else you may need it. And if you need some sort of notification that the property has changed (you need to do some change to the selectedProduct data and then show it), you can set a watcher function on the respective getter or just use computed properties that use the getter and they will pick up the change.
You can find out more about actions at https://vuex.vuejs.org/guide/actions.html
i'm new to Vue and Nuxt and i'm building my first website in Universal mode with these framework.
I'm a bit confused on how the store works in nuxt, since following the official documentation i can't achieve what i have in mind.
In my store folder i have placed for now only one file called "products.js", in there i export the state like this:
export const state = () => ({
mistica: {
id: 1,
name: 'mistica'
}
})
(The object is simplified in order to provide a cleaner explanation)
In the same file i set up a simple getter, for example:
export const getters = () => ({
getName: (state) => {
return state.mistica.name
}
})
Now, according to the documentation, in the component i set up like this:
computed: {
getName () {
return this.$store.getters['products/getName']
}
}
or either (don't know what to use):
computed: {
getName () {
return this.$store.getters.products.getName
}
}
but when using "getName" in template is "undefined", in the latter case the app is broken and it says "Cannot read property 'getName' of undefined"
Note that in the template i can access directly the state value with "$store.state.products.mistica.name" with no problems, why so?
What am i doing wrong, or better, what didn't i understand?
Using factory function for a state is a nuxt.js feature. It is used in the SSR mode to create a new state for each client. But for getters it doesn't make sense, because these are pure functions of the state. getters should be a plain object:
export const getters = {
getName: (state) => {
return state.mistica.name
}
}
After this change getters should work.
Then you can use the this.$store.getters['products/getName'] in your components.
You can't use this.$store.getters.products.getName, as this is the incorrect syntax.
But to get simpler and more clean code, you can use the mapGetters helper from the vuex:
import { mapGetters } from "vuex";
...
computed: {
...mapGetters("products", [
"getName",
// Here you can import other getters from the products.js
])
}
Couple of things. In your "store" folder you might need an index.js for nuxt to set a root module. This is the only module you can use nuxtServerInit in also and that can be very handy.
In your products.js you are part of the way there. Your state should be exported as a function but actions, mutations and getters are just objects. So change your getters to this:
export const getters = {
getName: state => {
return state.mistica.name
}
}
Then your second computed should get the getter. I usually prefer to use "mapGetters" which you can implement in a page/component like this:
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters({
getName: 'products/getName'
})
}
</script>
Then you can use getName in your template with {{ getName }} or in your script with this.getName.
When I put this in my Vue component ...
// using store getter
computed: {
authenticated() {
return this.$store.getters.authenticated
}
}
... it works. The value for authenticated is reactive and the computed property returns true when the value in the vuex store is true.
This should work ... (and would be the right way according to the docs)
// using store state
computed: {
authenticated() {
return this.$store.state.authenticated
}
}
... but doesn't. The computed property is always false.
It doesn't even work on initial state, so I guess it has nothing to do with the action or mutation. The vuex store holds the correct values in the state and the getters (Firefox Vue DevTools).
My store looks like this:
const state = {
authenticated: authenticate.isAuthenticated(),
};
const getters = {
authenticated () {
return state.authenticated
}
};
const mutations = {
isAuthenticated (state, isAuthenticated) {
state.authenticated = isAuthenticated
}
};
So, it works with store getters but not with store state. Afaik the store state should be reactive as well.
Any idea what I might be doing wrong?
More as an aside to this discussion, vuex offers the mapGetters, mapState, mapActions, and mapMutations helper functions.
In the case of the authenticated getter, you would map it like:
import { mapGetters } from 'vuex
computed: {
...mapGetters({
authenticated: 'authenticated'
})
}
Helps to keep your code clean and concise, imo.
Assuming you construct your Vuex.Store as I do below, the computed works as expected using either state.authenticated or getters.authenticated.
The mutations section made no difference, so I took it out to make things minimal.
As Bert noted, your getter should take state as a parameter; otherwise, it is using the declared const, which is the same thing in this case, but deceptive to read.
const authenticate = {
isAuthenticated() {
return true;
}
};
const state = {
authenticated: authenticate.isAuthenticated()
};
const getters = {
authenticated (state) {
return state.authenticated;
}
};
const store = new Vuex.Store({
state,
getters
});
new Vue({
el: '#app',
store,
computed: {
authenticated() {
return this.$store.state.authenticated;
}
}
});
<script src="//unpkg.com/vue#latest/dist/vue.js"></script>
<script src="//unpkg.com/vuex#latest/dist/vuex.js"></script>
<div id="app">
Anything? {{authenticated}}
</div>
const state = {
authenticated: authenticate.isAuthenticated(),
};
The state is an object. An attribute in the object is trying to call the result of a function. This might be the problem, as it would be asking an object to invoke functions. Try setting it to a fixed value first, and change the state value by invoking a mutation when needed.
You could also try js object function call to invoke the authenticate.isAuthenticated() function inside the state object.
Details here: https://www.w3schools.com/js/js_function_call.asp
Possible solution:
const state = {
authenticated: function(){ return authenticate.isAuthenticated() },
};
I do not think the problem is with using getters or state. Since state ran correctly, getters should do the same since it is pointing to state. Have you exported getters from your store? That seems to be the likely issue. As previously mentioned, you ought to pass state as a parameter when using vuex getters
This is my module:
const ModuleA={
namespaced:true,
state:{
categoryList:[
{name:'all', isActive:true},
{name:'negotiation', isActive:false},
]
},
getters:{
getCategory:(state)=>(index)=>{
return state.categoryList[index];
},
}
}
Without namespaced:true, I can call getCategory with this.$store.getters.getCategory(this.index).
How to call getCategory with namespaced:true? I can't use mapGetters because I have to pass parameter to the function.
See 2nd answer to this How to access Vuex module getters and mutations
this.$store.getters['ModuleA/getCategory'](this.index)