Vuex getter method returns undefined - javascript

I am trying to call a getter method and it's not getting called for some reason. If I console.log the store I can see that it's undefined:
This is where I'm calling the getter method:
computed: {
client() {
console.log(this.$store); //see above screenshot
console.log(this.$route.params.id); //shows a valid value.
//nothing seems to happen after this point, console.log in the below getter doesn't happen.
return this.$store.getters['clients/clientById', this.$route.params.id];
}
},
here's my getter in clients.js module:
getters: {
clients(state) {
return state.clients;
},
hasClients(state) {
return state.clients.length > 0;
},
clientById(state, id) {
console.log('test'); //this doesn't happen
return state.clients.find(client => client.id === id);
}
}
The first 2 getter methods are working fine, using the same syntax as what I'm doing when I'm calling the clientById getter.
What I'm trying to accomplish is to have an array of client objects, and then when a user clicks on a client in the client list, I grab the ID out of the route params and the appropriate client data is displayed on the page. I'd appreciate any guidance on whether I'm approaching this in the right way as well as I'm new to Vue.
state() {
return {
clients: [
{
id: null,
client_name: '',
address: '',
city: '',
state: '',
zip:'',
created_at: '',
updated_at: '',
deleted_at: null
},
]
};
},
UPDATE:
I'll provide my entire clients.js module in case something is off with that. Everything else seems to be working fine, so not sure if this is related or not. This is an updated version of the getter where I changed it to an arrow function based on your feedback. When I do this, I get another error: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.
I've also tried hard-coding the ID within the getter method and taking it out of the passed-in ID parameter, and that seems to work, but is returning undefined, so it's still not getting a value from state.
import axios from "axios";
export default {
namespaced: true,
state() {
return {
isLoading: false,
clients: [
{
id: null,
client_name: '',
address: '',
city: '',
state: '',
zip:'',
created_at: '',
updated_at: '',
deleted_at: null
},
]
};
},
mutations: {
setLoadingStatus(state, status) {
state.isLoading = status;
},
setClients(state, clients) {
state.clients = clients;
}
},
actions: {
async fetchClients(context) {
context.commit('setLoadingStatus', true);
try {
const resp = await axios.get('http://localhost/api/clients');
context.commit('setLoadingStatus', false);
context.commit('setClients', resp.data);
} catch(e) {
console.log(e);
}
}
},
getters: {
clients(state) {
return state.clients;
},
hasClients(state) {
return state.clients.length > 0;
},
clientById: (state) => (id) => {
return state.clients.find(client => client.id === id);
}
}
};

Related

Unexpected asynchronous action in "" computed property vue/no-async-in-computed-properties Vue3

I am developing my project with Vue3 , I am getting this error while running, here is my whole code . Can someone help me fix it. Thank you guys
<script>
import axios from 'axios';
export default {
name: "RegisterView",
data() {
return {
user: {
username: "",
password: "",
email: "",
phoneNumber: "",
role: "",
},
role : []
};
},computed:{
getRole(){
axios.get('http://localhost:8080/api/role/get').then(res=>{
this.role = res.data;
})
return [];
}
},
methods: {
register() {
axios.post("http://localhost:8080/api/user/register", this.user).then((res) => {
console.log(res.data);
});
},
},
};
</script>
// Error Unexpected asynchronous action in "getRole" computed property vue/no-async-in-computed-properties
I tried async and await , but it seems I got it wrong
Try to run that call inside the created hook :
import axios from 'axios';
export default {
name: "RegisterView",
data() {
return {
user: {
username: "",
password: "",
email: "",
phoneNumber: "",
role: "",
},
role : []
};
},
created(){
this.getRole():
},
methods: {
getRole(){
axios.get('http://localhost:8080/api/role/get').then(res=>{
this.role = res.data;
}).catch(err=>{
this.role = []
})
},
register() {
axios.post("http://localhost:8080/api/user/register", this.user).then((res) => {
console.log(res.data);
});
},
},
};
GetRole uses promises, meaning it doesn't have immediate value but has side-effects, which is considered to be dirty code by the linter (code quality checker)
If you need async computed, use asyncComputed instead, which has immediate value and gets updated of promise resolution automatically
https://github.com/foxbenjaminfox/vue-async-computed for Options API, #vueuse/core for Composition API

Reactive queries Apollo graphql in Vue 3

Trying to make a reactive query as per https://v4.apollo.vuejs.org/guide-option/queries.html#reactive-query-definition, but I can't get them to work.
Error:
Uncaught (in promise) Error: Invalid AST Node: { query: { kind: "Document", definitions: [Array], loc: [Object] }, loadingKey: "loading" }.
Query inside export default (checked is a reactive boolean v-model'ed to a button defined in data()):
apollo: {
getTags: getTags,
getPhotos: {
query() {
if (this.checked)
return {
query: getPhotos,
loadingKey: "loading",
}
else {
return {
query: getPhotosByTag,
loadingKey: "loading",
}
}
},
update: (data) => data.getPhotos || data.getPhotos,
},
},
GQL getPhotosByTag:
const getPhotosByTag = gql`
query getPhotosByTag {
getPhotos: findTagByID(id: 326962542206255296) {
photos {
data {
name
description
_id
}
}
}
}
`
GQL getPhotos:
const getPhotos = gql`
query getPhotos {
getPhotos: getPhotos(_size: 50) {
data {
name
description
_id
}
}
}
`
If I take them out into separate queries and try to instead update use skip() via checked and !checked in the query definition, only the initial load delivers a query, if I click the button new query doesn't launch. Queries work by themselves fine.
apollo: {
getPhotos: {
query() {
return this.checked ? getPhotos : getPhotosByTag
},
loadingKey: "loading",
update: (data) => data.getPhotos || data.getPhotos,
},
},
Loading key has to be on the same level as query

Keep getting [Object Object] in hybrid app Javascript

I'm building a hybrid app using Nuxt JS, Cordova and Cordova Native Storage (essentially localstorage).
I'm saving an object to native storage, and retrieving it on page load within mounted() however, I keep getting the following error no matter what I try to access the object data:
[Object Object]
My JS in the component which is loaded on every page is:
import { mapState } from 'vuex';
export default {
mounted () {
document.addEventListener("deviceready", this.getNativeStorage(), false)
},
methods: {
getNativeStorage() {
window.NativeStorage.getItem("beacon_native_storage", (value) => {
var parseObj = JSON.parse(value)
alert(parseObj)
alert(parseObj.localStorage)
}, (error) => {
alert(`Error: ${error.code}-${error.exception}`)
});
},
refreshNativeStorage(currentState) {
window.NativeStorage.initWithSuiteName("beacon");
window.NativeStorage.setItem("beacon_native_storage", JSON.stringify(currentState), () => {
alert('Stored currentState')
}, (error) => {
alert(`Error: ${error.code}`)
});
}
},
computed: {
state () {
return this.$store.state
}
},
watch: {
state: {
handler: function (val, Oldval) {
setTimeout(function () {
this.refreshNativeStorage(this.state)
}.bind(this), 10)
},
deep: true
}
}
}
And the object from Vuex looks like:
export const state = () => ({
pageTitle: 'App name',
dataUrls: [],
intervalData: [],
settings: [],
experimentalFeatures: [],
customAlertSeen: false,
user: null,
account: null,
payloadOutput: null
})
Every time the getItem runs, alert(parseObj) always returns [Object Object] rather than for instance, the data. And if I try returningparseObj.localStorage.pageTitlewhich is clearly defined instore/localStorage.jsit returnsundefined`
Where am I going wrong here?
So, what happens, is that localStorage stores STRINGS, not objects.
When you save your item to localStorage, first convert it to a string, then parse it from a string when you retrieve it.
localStorage.setItem('a', {b:'c',d:'e'})
localStorage.getItem('a') // "[object Object]" <- note the quotes!
localStorage.setItem('a', JSON.stringify({b:'c',d:'e'}))
JSON.parse(localStorage.getItem('a')) // {b: "c", d: "e"}

How use a mutation function in a action function in Vuex?

I have this Vuex:
export default new Vuex.Store({
state: {
userInfo: {
nit_ID: { ID: '', Desc: '' },
userName: { ID: '', Desc: '' },
typeDocument: { ID: '', Desc: '' },
document: '',
},
globalPublicKey: 'ASDFGHJKL1234567890',
},
mutations: {
updateUserInfo(state, payload) {
state.userInfo = payload;
},
},
getters: {
userInfo: (state) => { return state.userInfo; },
},
actions: {
validateUserSession(context) {
var valido = false;
try {
let storageInfo = JSON.parse(
sjcl.decrypt(context.state.globalPublicKey, localStorage.userInfo)
);
if (localStorage.userToken === storageInfo.token) {
context.mutations.updateUserInfo(storageInfo);
valido = true;
}
} catch (e) {
console.error(e);
}
return valido;
},
},
})
But the problem is that I can't access to the mutation updateUserInfo(), I know that is easy to solved, only do the updateUserInfo process in my action, but the question is How can I use a mutation into a action?
In VueJS you can call a mutation from an action by calling context.commit, like this:
context.commit('mutationName', params)
params can be omitted if not parameters are passed to the mutation.
More on this here: vuex.vuejs.org/guide/actions.html
Actually you call a mutation from anywhere with a commit - but it's advised to use actions (so dispatch an action) that in turn commits the data (actually mutates the state).

Vue.js component data not being updated after GET

I have a component that contains a default object, and on create GETs a populated object. When trying to bind this.profile to the new object it seems to get the correct data in the method but the change is not pushed back to other uses of this.profile. Is there a way to force this change to be picked up by the rest of the script?
export default {
data() {
return {
profile: {
firstName: 'Seller First Name',
surname: 'Seller Surname',
username: '',
biography: 'Seller biography.',
phoneNumber: 'Seller Phone Number',
emailAddress: 'Seller Email',
profilePhotoUrl: '',
testimonials: []
}
};
},
components: {
ProfileSummary,
Biography,
TestimonialList,
PaymentsenseCompany
},
created() {
console.log('created');
this.getProfile(this.$route.params.sellerUsername);
},
methods: {
getProfile(sellerUsername) {
axios.get('http://fieldsellerprofileapi.azurewebsites.net/api/fieldseller/' + sellerUsername)
.then(function(response) {
this.profile = Object.assign({}, response.data);
Vue.nextTick(() => {
console.log('after', this);
});
}.bind(this))
.catch(e => {
console.log(e);
// location.replace('/404');
});
}
},
Im not sure, but try this:
getProfile(sellerUsername) {
axios
.get('http://fieldsellerprofileapi.azurewebsites.net/api/fieldseller/' + sellerUsername)
.then(r => this.profile = r.data)
.catch(e => console.log(e))
}
So it turns out the issue wasn't that the values weren't being updated. They were being saved fine, I was just trying to access them in a child component which was not being updated with the parent for some reason. The changes were not propagating down to the children... This may be of use researching if you have the same issue.
Thanks

Categories

Resources