I am having troubles updating the DOM after fetching from an API.
My object is fetching the data correctly but the DOM is being rendered before and it won't update after receiving the API Data, I can't seem to understand why is not updating itself.
Here is my code:
<template>
<div>
<h1>Weather</h1>
{{ weather }}
</div>
</template>
<script>
export default {
name: 'Weather',
data() {
return {
weather : {},
}
},
created() {
this.getWeather()
},
methods: {
async getWeather() {
let self = this;
try {
const response = await fetch('https://api.weatherbit.io/v2.0/current?city=Berlin&country=DE&key=KEY');
const myJson = await response.json();
self.weather.temp = myJson.data[0].temp;
self.weather.sensation = myJson.data[0].app_temp;
self.weather.description = myJson.data[0].weather.description;
} catch (error) {
console.error(error);
}
}
</script>
You should assign the response value to the weather property directly like this.
methods: {
async getWeather() {
let self = this;
try {
const response = await fetch('https://api.weatherbit.io/v2.0/current?city=Berlin&country=DE&key=dcbea1b771ab41f09cd6b138d8cd50c2');
const myJson = await response.json();
self.weather = myJson.data[0].temp;
console.log(self.weather);
} catch (error) {
console.error(error);
}
}
}
Here is the working example.
https://jsfiddle.net/srfpw785/
I think you should insert your logic inside mounted() , not in created() , this should fix your problem with rendering.
<template>
<div>
<h1>Weather</h1>
{{ weather }}
</div>
</template>
<script>
export default {
name: 'Weather',
data() {
return {
weather : {},
}
},
mounted() {
this.getWeather()
},
methods: {
async getWeather() {
let self = this;
try {
const response = await fetch('https://api.weatherbit.io/v2.0/current?city=Berlin&country=DE&key=dcbea1b771ab41f09cd6b138d8cd50c2');
const myJson = await response.json();
self.weather.temp = myJson.data[0].temp;
self.weather.sensation = myJson.data[0].app_temp;
self.weather.description = myJson.data[0].weather.description;
} catch (error) {
console.error(error);
}
}
</script>
These are the steps in Vue lifecycle :
beforCreate,
created,
beforeMount,
mounted,
beforeUpdate,
updated,
beforeDestroy,
destroyed
Hope this will help you to understand Vue lifecycle :)
Related
Hi I'm a beginner in react and I have the following code
import { useCallback } from 'react';
import { useMutation } from '#apollo/client';
import { useCartContext } from '#magento/peregrine/lib/context/cart';
export const useWishlistAllItems = props => {
const { items,mutations } = props;
const { addSimpleWishListItemToCartMutation } = mutations;
const [{ cartId }] = useCartContext();
const [addWishlistItemToCart, { error, loading }] = useMutation(addSimpleWishListItemToCartMutation);
const handleAddAllItemsToCart = useCallback(async () => {
try {
items.map((item,index) => {
if (item.product.__typename !== 'ConfigurableProduct'){
const cartItem = {
data: {
quantity: 1,
sku: item.product.sku
}
};
addWishlistItemToCart({
variables: {
cartId,
cartItem
}
});
}
})
} catch {
return;
}
}, [addWishlistItemToCart, cartId, items]);
const saveWishList = useCallback(async () => {
try {
window.location.reload(false);
}catch {
return;
}
}, []);
return {
handleAddAllItemsToCart,
saveWishList,
hasError: !!error,
isLoading: loading
};
};
The problem is that the error is displayed before the error is returned to my main component.I get the following
I have handled the returned error in my component properly but the problem is I get the error as above before returned to the component.I think It is because of the callback function.Please give me a solution.
Running async method without await is like just starting Task without
monitoring it's progress and results.
So, once again check your code using await and return the appropriate output.
I need to get data with axios and send them to my calendar with the 'splitDays' table and I have to change the variable name of my data to put "class" and "label"
I can recover my data but when I leave the axios I go to undefined
data() {
return {
splitDays:[], // :splitDays
};
},
mounted() {
axios
.get(`${process.env.*****}/users?role=***&active=***`)
.then(response => ( this.users = response.data,
console.log(this.users)
))
console.log(this.users)
/*
for (let splitDayIndex in mySplitDays){
let splitDay= mySplitDays[splitDayIndex]
splitDay.class = splitDay.lastname
splitDay.label = splitDay.lastname
mySplitDays[splitDayIndex]=splitDay
}
*/
},
I'm not sure I understand what you mean by when I leave the axios I go to undefined, but your second console.log(...) will be executed before your axios call finishes. Try with:
data() {
return {
splitDays:[], // :splitDays
};
},
async mounted() {
let response = await axios
.get(`${process.env.AFFECTIT_API}/users?role=Collaborateur&active=1`)
this.users = response.data
console.log(this.users)
/*
for (let splitDayIndex in mySplitDays){
let splitDay= mySplitDays[splitDayIndex]
splitDay.class = splitDay.lastname
splitDay.label = splitDay.lastname
mySplitDays[splitDayIndex]=splitDay
}
*/
},
I'm fooling around trying to learn stuff (Vue.js 2 with routing) and I was wondering why whenever I was on any other routes other than the home ('/') route, said localhost url gets prepended to the appropriate url when making API calls. An example would be the following:
const url = `'https://www.reddit.com/r/'${ this.sub }/.json?limit=10'`; // this.sub being the corresponding subreddit string
which results in something like this:
'http://localhost:5000/subreddits/politics/https://www.reddit.com/r/politics/.json?limit=10'
Below is the relevant code:
<script>
export default {
data() {
return {
sub: this.$route.params.sub,
posts: [],
}
},
watch: {
'$route'(to, from) {
this.sub = to.params.sub;
}
},
methods: {
fetchPosts: async function () {
const url = `'https://www.reddit.com/r/'${ this.sub }/.json?limit=10'`;
try {
const res = await (await fetch(url)).json();
this.posts = await (res.data.children);
} catch(err) {
console.error(err);
}
}
},
mounted() {
this.fetchPosts();
},
}
</script>
There are 2 problems in your project.
1. The request whose host is reddit can't be send within localhost.
2. if you use back quote, single quote is redundant.
IF YOU USED VUE-CLI TO INIT THE PROJECT, to solve these problem, there are 2 step you should do.
in /config/index.js file, find proxyTable, and add this:
```
proxyTable: {
'/reddit': {
target: 'https://www.reddit.com/r',
changeOrigin: true,
pathRewrite: {
'^/reddit': ''
}
}
}
in the relevant code:
```
<script>
export default {
data() {
return {
sub: this.$route.params.sub,
posts: [],
}
},
watch: {
'$route'(to, from) {
this.sub = to.params.sub;
}
},
methods: {
fetchPosts: async function () {
const url = `/reddit/'${ this.sub }/.json?limit=10`;
try {
const res = await (await fetch(url)).json();
this.posts = await (res.data.children);
} catch(err) {
console.error(err);
}
}
},
mounted() {
this.fetchPosts();
},
}
</script>
```
I have setup vuex and i would like to later fetch the data and update my form model but this fails
In my vuex
//state
const state = {
profile: [],
}
//getter
const getters = {
profileDetails: state => state.profile,
}
//the actions
const actions = {
getProfileDetails ({ commit }) {
axios.get('/my-profile-details')
.then((response) => {
let data = response.data;
commit(types.RECEIVED_USERS, {data});
},
);
}
}
const mutations = {
[types.RECEIVED_USERS] (state, { data }) {
state.profile = data;
state.dataloaded = true;
},
}
Now in my vue js file
export default{
data: () => ({
profile_form:{
nickname:'',
first_name:'',
last_name:'',
email:''
}
}),
computed:{
...mapGetters({
user: 'profileDetails',
}),
},
methods:{
setUpDetails(){
this.profile_form.email = this.user.email; //the value is always undefined
}
},
mounted(){
this.$store.dispatch('getProfileDetails').then(
(res)=>{
console.log(res); //this is undefined
this.setUpDetails(); ///this is never executed
}
);
this.setUpDetails(); //tried adding it here
}
By checking with the vue developer tools i can see that the vuex has data but my component cant fetch the data in vuex after calling the dispatch in the action to fetch the data.
Where am i going wrong.
Nb: AM using the data to update a form like this
<input v-model="profile_form.email" >
Your mounted method expects a return (res) from getProfileDetails, but the action isn't returning anything, so you could simply try
const actions = {
getProfileDetails ({ commit }) {
return axios.get('/my-profile-details')
.then((response) => {
let data = response.data;
commit(types.RECEIVED_USERS, {data});
return data // put value into promise
},
);
}
}
However, it's more usual to commit to store from within the action (which you are doing) and let the component get the new values from a getter (which you have) - i.e one-way-data-flow.
This is how I'd set it up.
data: () => ({
profile_form:{
nickname:'',
first_name:'',
last_name:'',
email:''
}
}),
mounted(){
this.$store.dispatch('getProfileDetails')
}
computed: {
...mapGetters({
user: 'profileDetails',
}),
}
watch: {
user (profileData){
this.profile_form = Object.assign({}, profileData);
}
},
methods:{
submit(){
this.$store.commit('submituser', this.profile_form)
}
},
As a beginner to vue.js I'm struggling with this problem for days.
I know that there are few plugins for that:
vue-google-auth
and
vue-google-signin-button
and
vue-authenticate
But none of these come with good documentations, so my attempts to make use of them failed.
I also could not find any tutorial on vue.js with OAuth2 authentication after extensive googling. So appreciate if someone could come up with a full working example or refer me to some complete code.
Example of usage without any plugins:
index.html
<meta name="google-signin-client_id" content="your-client-id.apps.googleusercontent.com"
/>
<script src="https://apis.google.com/js/platform.js"></script>
App.vue
<template>
<div v-show="!profile" id="g-signin2"></div>
<div v-if="profile">
<pre>{{ profile }}</pre>
<button #click="signOut">Sign Out</button>
</div>
</template>
<script>
export default {
mounted() {
this.initGoogleAuth();
this.renderGoogleAuthButton();
},
data() {
return {
profile: null
};
},
methods: {
onSignIn(user) {
const profile = user.getBasicProfile();
const fullName = profile.getName();
const email = profile.getEmail();
const imageUrl = profile.getImageUrl();
this.profile = { fullName, email, imageUrl };
},
signOut() {
var auth2 = window.gapi.auth2.getAuthInstance();
auth2.signOut().then(() => {
console.log("User signed out");
this.profile = null;
});
},
initGoogleAuth() {
window.gapi.load("auth2", function () {
window.gapi.auth2.init();
});
},
renderGoogleAuthButton() {
window.gapi.signin2.render("g-signin2", {
onsuccess: this.onSignIn
});
}
}
};
</script>
This is a working example with vue-google-oauth2.
You can install it with:
npm i vue-google-oauth2
Then you need to place these 2 lines of code in your APP ENTRY file, e.g. src/main.js
import GAuth from 'vue-google-oauth2'
Vue.use(GAuth, {clientId: 'XXXXXXXX'})
Where XXXXXXXX is the clientId you get from https://console.cloud.google.com/apis/
I will assume you have been there if you've tried to login with Google before.
Then you create this component
<template>
<div>
<h1>Test</h1>
<button #click="handleClickGetAuth" :disabled="!isInit">get auth code</button>
<button #click="handleClickSignIn" v-if="!isSignIn" :disabled="!isInit">signIn</button>
<button #click="handleClickSignOut" v-if="isSignIn" :disabled="!isInit">signOout</button>
</div>
</template>
<script>
export default {
name: 'test',
data () {
return {
isInit: false,
isSignIn: false
}
},
methods: {
async handleClickGetAuth() {
try {
const authCode = await this.$gAuth.getAuthCode()
const response = await this.$http.post('http://your-backend-server.com/auth/google', { code: authCode, redirect_uri: 'postmessage' })
} catch (error) {
// On fail do something
}
},
async handleClickSignIn(){
try {
const googleUser = await this.$gAuth.signIn()
console.log('user', googleUser)
this.isSignIn = this.$gAuth.isAuthorized
} catch (error) {
// On fail do something
console.error(error);
return null;
}
},
async handleClickSignOut(){
try {
await this.$gAuth.signOut()
this.isSignIn = this.$gAuth.isAuthorized
} catch (error) {
// On fail do something
}
}
},
mounted(){
let that = this
let checkGauthLoad = setInterval(function(){
that.isInit = that.$gAuth.isInit
that.isSignIn = that.$gAuth.isAuthorized
if(that.isInit) clearInterval(checkGauthLoad)
}, 1000);
}
}
</script>
All credits goes to
https://github.com/guruahn/vue-google-oauth2/blob/master/sample.html