Vuex. Cannot use rootState in a getter of a module - vuex

I have this in my root store
In a module I define this getter
selectedFermentables: (state,rootState) => {
let prefs =rootState.userPreferences.brands_fermentable;
state.fermentables.forEach((f) => {
if (prefs.indexOf(f.brand_id)!= -1) {
result.push(f);
}
});
return result;
},
My app crashes saying
Uncaught (in promise) TypeError: rootState.userPreferences is
undefined
I tried many things without success. Help would be welcome.

rootState needs to be the third argument... Even if you don't use 'state' or 'getters'
yourGetter: (state, getters, rootState) => {
return rootState
}
Strangely, getters dont receive named arguments...

Related

Nuxt store getter not working, ID given to payload is not an Integer + Error: [vuex] do not mutate vuex store state outside mutation handlers

I am trying to make a product detail page. The detail page is named _id.
When opened the id is replaced with the product id. On opening the page the state is set with data fetched from an api.
After that i am trying to use a computed property that refers to a getter named getProduct() with an id (this.$route.params.id) in the payload.
This is how my _id.vue looks like:
methods: {
...mapActions("products", ["fetchProducts",]),
...mapGetters("products", ["getProduct",]),
},
async mounted() {
this.fetchProducts()
},
computed: {
product() {
return this.getProduct(this.$route.params.id)
}
}
This is how my store file named products.js looks like:
import axios from "axios"
export const state = () => ({
producten: []
})
export const mutations = {
setProducts(state, data) {
state.producten = data
}
}
export const getters = {
getProduct(state, id) {
console.log(id)
return state.producten.filter(product => product.id = id)
}
}
export const actions = {
async fetchProducts({ commit }) {
await axios.get('/api/products')
.then(res => {
var data = res.data
commit('setProducts', data)
})
.catch(err => console.log(err));
}
}
What works is creating the state, but when i try to use the getter something goes wrong.
As you can see i console.log() the id given to it. Which logs the following:
I also get the error: client.js?06a0:103 Error: [vuex] do not mutate vuex store state outside mutation handlers.
Which I'm not doing as far as I know?
**Note: **these errors get logged as much as the length of my state array is.
From the Vuex documentation:
Vuex allows us to define "getters" in the store. You can think of them as computed properties for stores. Like computed properties, a getter's result is cached based on its dependencies, and will only re-evaluate when some of its dependencies have changed.
Like computed, getters does not support having arguments.
But there is a way to have "method-style access" to a getter: https://vuex.vuejs.org/guide/getters.html#property-style-access
You can also pass arguments to getters by returning a function. This is particularly useful when you want to query an array in the store:
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
Note that getters accessed via methods will run each time you call them, and the result is not cached.

How to return promise result from Vuex action instead of the promise itself?

I have an action in my vuex store:
export const actions = {
myaction() {
return 'foo'
}
}
Can I get the promise result (here foo) in the mounted() life cycle hook and display it in the console ? If yes, how ?
I tried this:
mounted() {
console.log(
this.$store
.dispatch('myaction')
.then(res => res)
)
}
But it returns the promise instead of the promise result I'm expecting.
Either of these should work:
Using .then():
mounted() {
this.$store
.dispatch('myaction')
.then(res => console.log(res));
}
Or if you're using ES2017 or later (or some compatibility tool like Babel), then you can use async/ await:
async mounted() {
const res = await this.$store.dispatch('myaction');
console.log(res);
}
As #Dan mentions below, whilst this will return you the value of the Promise, this is not the intended usage of Vuex, which prefers all data to be saved to and accessed from Vuex's state.
It would be better to mutate the store in your action to save the value and then use a computed property in your component to retrieve it from state, either directly or through a getter. This can be done very cleanly with the mapGetters Vuex helper function.

Nuxt - How to call a getters in a global mixins?

Hi everyone here is the mixin code I wrote as I want to use this for default.vue and error.vue layout. I am trying to avoid duplicating code in two layout.
export default {
provide () {
return {
copyRight: this.getCopyrightText,
email: this.getEmail,
socials: this.getSocials
}
},
computed: {
getMenu () {
return this.store.getters['general/getMenu'].menu
},
getSocials () {
return this.store.getters['general/getSocialDetails']
},
getCopyrightText () {
return this.store.getters['general/getCopyRight']
},
getEmail () {
return this.store.getters['general/getEmail']
}
},
middleware: 'load-menu-items'
}
This is what I get: Cannot read property 'length' of undefined
What am I doing wrong?
In your component I assume you're using .length on the data you're receiving from the getter method, which is probably where the error occurs.
First of all you should debug to see if your getter is actually working as expected. Try this and look at output in console for every getter computed property. If undefined is printed to the console you'll get the error you posted if you're using .length on it
getEmail () {
let data = this.store.getters['general/getEmail'];
console.log(data);
return data;
}
If you post the component which is using this mixin maybe I can help you further.

How to get access to store from action in VueJS?

Im using VueJS and Vuex. I have the userid into the store, this way:
vuex screenshot
And i try pass the userid to a fetch, but vuejs return error
([Vue warn]: Error in created hook: "TypeError: this.$store is
undefined")
import { LOAD_APPOINTMENTS } from './types'
export default {
loadProducts ({ commit }) {
var user = this.$store.state.user.userid
fetch('api/appointments/' + user)
.then((result) => {
return result.json()
})
.then((appointments) => {
commit(LOAD_APPOINTMENTS, appointments)
})
.catch(er => {
console.log(er)
})
}
}
First, when referencing the store within vuex files:
context.state instead of this.$store.state.
context for all of the this.$store. So, context.commit and context.dispatch.
Second, the loadProducts needs to be rewritten as an action per docs.
Third, loadProducts needs to incorporate the context as a parameter:
actions: {
loadProducts (context) {
...
context.commit(...)
...
}
}
As #phil has mentioned in this thread, it is important to view the documentation entirely, as this single answer will get you on the way to debugging the problem, but there might be multiple more problems showing up (e.g. fetch errors, file structure errors, component/App level errors).

Unable to access `get` method in vue-resource

I have a tiny vue app where I'm wanting to use vue-resource to request an api endpoint.
I've installed vue-resource via npm
I've added the Vue.use(VueResource) lines to my bootstrap file
I've setup my component like this to call the .get method
Blog.vue
...
mounted () {
this.fetchPosts()
},
methods: {
fetchPosts: () => {
debugger;
this.$http.get('my-url')
.then(response => {
console.log(response)
})
}
}
...
I've seen a few github issues and SO posts which touch on this type of problem but most seem to relate to incorrect configuration which I don't think I have (happy to be proven wrong!)
The specific console error I get is:
Error in mounted hook: "TypeError: Cannot read property 'get' of undefined"
What's odd about this is that if you see my debugger line, if I console.log this.$http.get at that point I get:
function (url, options$$1) {
return this(assign(options$$1 || {}, {url: url, method: method$$1}));
}
If I let the code run and then attempt the console.log afterwards I get:
Cannot read property 'get' of undefined
As a result I presume it's some kind of this context issue, but from what I can see the reference should be correct...shouldn't it?
Methods should not be arrows function. The this will not point to the vue instance if a methods is declared using arrow function.
Use normal function instead:
methods: {
fetchPosts(){
debugger;
this.$http.get('my-url')
.then(response => {
console.log(response)
})
}
You can see the warning here