Assigning res.data to variable returns null - javascript

I am trying to make a GET request to an API, assign the response to a variable and console.log it. Currently I get null in the console and I don't know why. when I just console.log the res.data I get the data, but for some reason the value does not get assigned to the variable allBeers, how can I save the response to that variable and use it?
Here is my code:
<script>
import axios from "axios";
export default {
name: "BeerList",
data() {
return {
allBeers: null
};
},
created() {
axios.get("https://api.punkapi.com/v2/beers").then(res => {
this.allBeers = res.data;
});
console.log(this.allBeers);
}
};
</script>

Try this solution. axios.get is a promise, and console.log will happen before axios.get is completed. That's why you get null.
<script>
import axios from "axios";
export default {
name: "BeerList",
data() {
return {
allBeers: null
};
},
created() {
axios.get("https://api.punkapi.com/v2/beers").then(res => {
this.allBeers = res.data;
console.log(this.allBeers);
});
}
};
</script>

You are saving the response to 'allBeers' variable correctly. The "how to use it" part depends on what you want to do with the data. Vue's 'data' is reactive, so if you want to print it to console when it changes you should use Vue's watcher in your component:
watch: {
allBeers: function(value) {
console.log("my new beers:");
console.log(value);
}
}
As Vue is UI framework you might want to update your html with the new data, in which case you need to add html template to your component - it will be automatically re-rendered when 'allBeers' change:
template: `<span> {{ allBeers }} </span>`

Related

I cannot read vuex-persist in v-if

I am trying to use vuex-persist on nuxt.js but when try to read the data in a v-if doesn't work.
I created a new file inside plugins called vuex-persis.js with the following code:
import VuexPersistence from 'vuex-persist'
export default ({ store }) => {
new VuexPersistence({
storage: window.localStorage,
}).plugin(store);
}
and into nuxt.config.js I added the following code:
plugins: [{ src: '~/plugins/vuex-persist', mode: 'client' }],
The code that I use in order to store and get data is the following:
this.$store.commit('login', { idToken });
store.state.isLogin
and I have added the following file inside the project ./store/index.js
export const state = () => ({
isLogin: false,
idToken: '',
});
export const mutations = {
login(state, newState) {
state.isLogin = true;
state.idToken = newState.idToken;
},
logout(state) {
state.isLogin = false;
state.idToken = '';
},
};
I have the following navbar when I try to get the data from store:
navbar-button(to='/board', v-if='$store.state.isLogin')
p {{ $t("navbar_board") }}
navbar-button(v-if='$store.state.isLogin', #click.native='logout')
p {{ $t("navbar_logout") }}
but always enter in the same place, log in.
I tried to use a computed like this but doesn't work on the v-if
computed: {
isLogin: function () {
console.log(this.$store.state.isLogin);
return this.$store.state.isLogin;
},
},
the console.log prints the value stored in the browser but the console.log in node prints always the default state.
Anyway, the console.log always prints the correct value stored in the localstorage.
Any idea about how can I use that data in the v-if?
Thanks
Finally solved directly using $store.state.isLogin in the v-if

Create Global Function For Checking If LocalStorage is not empty - Vue.JS

I'm just wondering how to create a global function wherein it checks whether the localStorage is not empty specifically if there's a token inside
What I've tried is creating a global variable in my main.js
Vue.$checkIfTokenIsNotEmpty = !!localStorage.getItem('token');
// this returns true or false
In my component,
<template>
Is token Empty? {{ isTokenIsEmpty }} // I'm able to get true or false here
</template>
<script>
export default {
data(){
return {
isTokenIsEmpty: this.$checkIfTokenIsNotEmpty
}
}
}
</script>
This works properly when I reload the page. The problem is, it's not reactive or real time. If I clear the localStorage, the value of my this.$checkIfTokenIsNotEmpty doesn't change. It only changes when I reload the page which is bad in my spa vue project.
You can acces token like here: https://jsfiddle.net/djsj8dku/1/
data: function() {
return {
world: 'world',
get token() {
return localStorage.getItem('token') || 0;
},
set token(value) {
localStorage.setItem('token', value);
}
};
}
Or you can use one of this packages: vue-reactive-storage, vue-local-storage
You cannot detect when localStorage is wiped out manually but you can watch when localStorage is updated. So watcher is what you need. Link
Regarding global function you can set a method & variable inside root component.
new Vue({
el:"#app",
data:{
isTokenIsEmpty:null
},
methods: {
checkIfTokenIsNotEmpty() {
this.isTokenIsEmpty= !!localStorage.getItem('token');
}
}
})
Inside component,
mounted(){
this.$root.checkIfTokenIsNotEmpty() //can be added anywhere when needed to check localStorage's Availablity
}
Html
<template> Is token Empty? {{ $root.isTokenIsEmpty }} // I'm able to get true or false here </template>

Chartjs + Vue.js - Cannot read property '_meta' of undefined

I am building an app using Vue.js + Chartjs. I am having a problem where I make a http call to a service to get data, parse it, and pass it into my Chartjs component. However, I keep getting the error Cannot read property '_meta' of undefined
Here are the relevant parts of my component:
<template>
<Chartjs :data="chartData" />
</template>
export default {
data () {
return {
chartData: false
}
},
created () {
this.getData()
},
methods: {
getData() {
const opts = {
url: 'some_url',
method: 'get'
}
request.callRoute(opts).then(results => {
this.chartData = results.data
}).catch(err => {
console.log(err)
})
}
},
components: {
Chartjs
}
}
Note - the chart renders fine if I hard code the chartData field with data that comes back from my request. However, it does NOT work if I make a http request first for my data.
Does anyone know what might be happening?
Thanks in advance!
Vue will render the component with the initial chartData (which is a boolean). You should use a v-if or other logic and render Chartjs component when you have the response. For example you can show a loading message/animation while the chartData is false.

Pass data into vuejs template

I have a Laravel application with vuejs2 support. Im using the router component in the vuejs part. How can I send data like sessions from laravel to a vuejs template. In my blade template I use <router-view ></router-view> to call the vue router component. How can I add data.
Thanks for help!
The page which you want to load using vuejs router component, add a script in the footer section of that page. And after using router push command, please refresh the whole page.
Keep a flag like: loading. At first, keep it true to view some initial message, and when you'll get axios response then make it false. Based on this flag, show the data that you get from axios response. And of course update the initially declared data after getting the axios response.
Example:
<script>
export default {
data(){
return {
loading:true,
// Others Data
}
},
methods:{
function_name (){
this.$router.push('/');
window.location.reload();
}
},
mounted() {
var _this = this;
axios.get('/data').then(function (response) {
//others data update
_this.loading=false;
});
}
}
</script>
You can use axios to make a get request to your laravel app.
Example method:
data() {
return {
data: ''
}
},
methods: {
getData: function () {
axios.get("/data")
.then((response) => {
this.data = response.data;
}, (error) => {
})
}
},
Note that you need to import axios in order to work:
import axios form 'axios'
Then you need to handle the request on the server side

Async Computed in Components - VueJS?

I'm finding a solution to async computed method in Components:
Currently, my component is:
<div class="msg_content">
{{messages}}
</div>
<script>
export default {
computed: {
messages: {
get () {
return api.get(`/users/${this.value.username}/message/`, {'headers': { 'Authorization': 'JWT ...' }})
.then(response => response.data)
}
}
},
}
</script>
Result:
{}
How to rewrite it in Promise mode? Because I think we can async computed by writing into Promise mode.
Computed properties are basically functions that cache their results so that they don't have to be calculated every time they are needed. They updated automatically based on the reactive values they use.
Your computed does not use any reactive items, so there's no point in its being a computed. It returns a Promise now (assuming the usual behavior of then).
It's not entirely clear what you want to achieve, but my best guess is that you should create a data item to hold response.data, and make your api.get call in the created hook. Something like
export default {
data() {
return {
//...
messages: []
};
},
created() {
api.get(`/users/${this.value.username}/message/`, {
'headers': {
'Authorization': 'JWT ...'
}
})
.then(response => this.messages = response.data);
}
}
es7 makes doing this quite trivial by using async and await in conjunction with axios' returned promise. You'll need the vue-async-computed package.
export default {
asyncComputed: {
async myResolvedValue() {
return await api.get(`/users/${this.value.username}/message/`, {'headers': { 'Authorization': 'JWT ...' }})
.then(response => response.data)
}
}
}
I bumped on a similar case where I need to re-run the computed function to fetch from a server every time a data or a props changes.
Without installing any extra package (vue-async-computed or vue3-async-computed as pointed by other answers), you can force a data to reload by creating a "virtual" computed method.
Lets say you want to fetch data from the server every time the user types their username, and depending on what was typed, you want to show a given message from the server.
From the example below, username and messages in this case are both reactive data, but there is no direct connection between them, so lets create a computed that depends on username by returning its value, which will force it to be called every time username is changed. Now you just need to call a function that can be async and will update messages after fetching from the server.
In the example below, I use ":dummy" just to force a call to my computed function.
<template>
<input v-model="username">
<div class="msg_content" :dummy="force_react">
{{messages}}
</div>
</template>
<script>
export default {
data: function () {
return {
messages: "",
username: "",
};
},
computed: {
force_react: function() {
this.get(); // called every time that this.username updates
return this.username; // becase its result depends on username
}
},
methods: {
async get() { // get's called every time that this.username updates
console.log("Got called");
let response = await api.get(`/users/${this.username}/message/`, {'headers': { 'Authorization': 'JWT ...' }});
this.messages = response.data;
}
},
}
</script>
You can see a working example here in Vue SFC playground
Why not using a watcher? Vue Documentation
You can use async function in the callback of the watcher.

Categories