Vue localforage no update - vue.js

I'm using localforage, but I can't figure out why this.emails is not updated outside the localforage. I get no errors in console.
localforage.getItem("emails").then(function (value) {
this.emails = value
console.log(value) // shows correct value
console.log(this.emails) // shows correct value
}).catch(function (err) {
console.log(err); // no error is thrown
});

Functions have a this scope. So when you're setting this.emails, you're setting the function's this.emails instead of your Vue component.
You could use bind to deal with this, but the easier way would be to just use an anonymous function in your then, like this:
localforage.getItem("emails").then((value) => {
this.emails = value
})

Related

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.

Vue.js, VueX - cannot render data from API in a component

I want to make an API call to the server to fetch the data and then display them in a component. I have a created() method which dispatches an action to my store, which, in turn, commits the mutation to udpate my store with the data I got from the server. I also have computed method where I simply call the getter which fetches the data from the store. The code looks like this:
state
state: {
data: {
rides: []
}
}
component.vue
created() {
this.$store.dispatch('fetchUserRides');
}
computed: {
...mapGetters([
'userRides'
]),
}
store.js
//actions
fetchUserRides({ commit }) {
axios.get('/api/stats/current_week')
.then(response => {
commit('fetchUserRides', response)
})
.catch(error => {
commit('serverResponsError')
})
//mutations...
fetchUserRides(state, payload){
let rides = payload.data
rides.forEach((item) => {
state.data.rides.push(item)
})
//getters
userRides: state => {
let rides = state.data.rides
rides.sort(( a, b) => {
return new Date(a.date) - new Date(b.date);
});
return rides
}
I receive over 40 objects in the response, I did check it by console.log(state.data.rides) and they are there in 100%.
My problem is that when I log off and log back in again it throws an error "TypeError: Cannot read property 'sort' of null". But if I hit Refresh they appear fine. The login action redirects me to the page where I render this component. This looks like the computed property first tries to fetch data by the getter from the array before it is actually populated in the store. How can I make sure I get the array of objects in my component?
You probably need to set an empty array ([]) as an initial value to state.data.rides instead of null.
Another option will be to check that rides is truthy in your getters.
Something like:
if (rides) {
rides.sort(( a, b) => {
return new Date(a.date) - new Date(b.date);
});
}
return []
I was able to resolve my problem and it turns out I made a mistake. I completely forgot I set state.data.rides = null instead of an empty array state.data.rides = null, which would explain why the array was empty. It was a legacy code I had :)

Vue redirecting. My code is note redirecting to the page i want to

it is not redirecting to the page. What am I doing wrong here?
this method is getting all the data from the form and adding dynamic values to date and token.
methods:{
addToApi() {
console.log(this.data);
crypto.randomBytes(20,(err,buff)=>{
let token = buff.toString('hex');
let sub = this.data.sub;
let date = Date.now() + 3600000;
let newData = {
sub: this.data.sub,
token: token,
date: date
}
axios.post("http://localhost:3000/api/qrData",newData)
.then((res)=>{
//after sending the data to back end it should redirect to this route but it doesn't redirect
router.go('/');
})
.catch((err)=>{
console.log(err);
})
})
}
}
}
check Vue Router: Programing Navigation,
As the tutorial said:
router.go(n)
This method takes a single integer as parameter that indicates by
how many steps to go forwards or go backwards in the history stack,
similar to window.history.go(n).
For your use case, you should use router.push
The main problem is that you refer to this variable which in this certain case has different values over the scopes. The common solution is to create a new variable storing this as I did it in the first line of addToApi() method.
Getting to the point, variable router is undefined in the method's scope. You should use this.$router which refers to the global router object. And as this variable loses its value in then function (change of scope), you want to use vm variable I defined. So your code should finally look like this below:
As pointed in the comment, arrow functions do not carry this variable.
If you want to redirect to a particular route you should use $router.push method instead. (go method was used in Vue Router's older versions and renamed to push in 2.x)
methods: {
addToApi() {
crypto.randomBytes(20, (err, buff) => {
let token = buff.toString('hex');
let sub = this.data.sub;
let date = Date.now() + 3600000;
let newData = {
sub: this.data.sub,
token: token,
date: date
}
axios.post("http://localhost:3000/api/qrData", newData)
.then((res) => {
//after sending the data to back end it should redirect to this route but it doesn't redirect
this.$router.push('/');
})
.catch((err) => {
console.log(err);
})
})
}
}
}

Stumped. How do i get data in vue from axios to display?

I have an axios call to an api that calls 22 objects in an array.
I want to save this from a computed, to data, then i want to loop through this in a select option with v-for.
Something like this:
<option v-for="item in items">{{item}}</option>
computed: {
items(){
return axios.post('API Call').then(response =>{ this.items =
response.data });
}
}
But I cannot for the life of me figure out where im going wrong.
As is usually the case, i resolved this by just hacking away at it. this is what i did to resolve the issue:
option:
<option v-for="item in data" :value='item.id'>{{item.name}</option>
method:
test_data: function(){
var self = this;
axios.post('API Call Here', {})
.then(response => {
self.data = response.data;
})
.catch(function(error){
console.log(error);
})
}
And the data:
data () {
return {
data:''
}
}
Assigning this.items (as if it were a variable) inside this.items (which is a function: the computed property items) looks kinda wrong to me, but I've never seen that so I don't know the effect that has.
On the other hand, axios returns a promise, so if your computed is doing return axios.whatever().then(etc) you are going to get a promise out of the computed property, which is probably not what you want.
I think in this case you want to have items be a normal data property, and then do the axios call in a method or life cycle hook, or a watcher, and then when you do this:
data() {
return {
items: [some default initial value here]
}
},
created() {
var self = this;
axios.post('API Call').then(response => {
self.items = response.data
});
}
items (now a data prop) will get assigned to response.data whenever the promise resolves successfully. (Notes: You probably know how your api formats your responses, but just in case, make sure response.data is actually what you want instead of, say, response.body.data or something. And make sure to add a catch or a rejection handler somewhere at some point too. EDIT: Whoops yeah, the other answer reminded me I forgot the "self")

React Native AsyncStorage: Accessing Value from Promise Object

When I use AsyncStorage.getItem() to retrieve the value (an email address) of a specified key, it returns a Promise object as indicated in the documentation. The value appears in object like so:
{
_45: 0
_54: null
_65: "testuser#test.com"
_81: 1
}
Can I reliably access this value by calling obj._65 or is there another way to accomplish this?
AsyncStorage return a promise. you can use .then for get value
exemple:
AsyncStorage.getItem('key').then((keyValue) => {
console.log(keyValue) //Display key value
}, (error) => {
console.log(error) //Display error
});
Looking at the docs you should be able to do this reliably to retrieve data from your async storage object.:
try {
const value = await AsyncStorage.getItem('#MySuperStore:key');
if (value !== null){
// We have data!!
console.log(value._65);
}
} catch (error) {
// Error retrieving data
}
you must use this within a function that is async however or you will get a runtime exception.