Vue.js component not loading/rendering data when called via URL or F5 - vue.js

I have a Vue.js SPA with some pages that display data from a backend. When I navigate the pages via the navbar, everything works fine, components and data are loaded.
When I'm on the page, e.g. localhost:8080/#/mypage and press F5, the data doesn't get loaded / rendered. Same goes for when I directly navigate to the page via the address bar.
The data gets loaded in this function:
async beforeMount() {
await this.initializeData();
}
I've tried to call the method in every lifecycle hook, i.e. created, beforeCreated, mounted etc...
In the mounted lifecycle hook I'm setting a boolean property to true, so that the table is only rendered when the component is loaded (done with v-if).
mounted() {
this.componentLoaded = true;
}
Not sure if this is important, but I've tried it with or without and it doesn't work.
I would really appreciate it if somebody knew whats happening here.
EDIT:
this.applications is a prop and contains multiple applications which contain instances. I want to add some variables from the backend to each application.
console.log(1) gets printed
console.log(2) does not
initializeData: function () {
let warn = 0;
console.log("1");
this.applications.forEach(async application => {
const instance = application.instances[0];
console.log("2");
let myData = null;
try {
const response = await instance.axios.get('url/myData');
myData = response.data;
} catch (err) {
}
let tmpCount = 0;
let tmpFulfilled = 0;
myData.forEach(ba => {
if(!ba.fulfilled){
warn++;
application.baAllFulfilled = false;
}else {
tmpFulfilled++;
}
tmpCount++;
})
console.log("3");
// Assign values
this.baTotalWarnings = warn;
application.baAnzahl = tmpCount;
application.baFulfilled = tmpFulfilled;
this.componentLoaded = true;
}

Try removing the async and await keywords from your beforeMount, and remove this.componentLoaded from mounted. Set it instead in the then block (or after await) in your initializeData method. I'm not sure Vue supports the async keyword in its lifecycle methods.
Something like this:
beforeMount() {
this.initializeData(); // start processing the method
}
methods: {
initializeData() {
callToBackend().then(() => {
this.componentLoaded = true // backend call ready, can now show the table
})
}
}

Related

React-Native async-storage putting functions in common js file?

In React-native (to which I'm relatively new), I use async storage to store a list of favourites between sessions.
eg
const StoreFavourites = async (sFavourites) => {
try {
await AsyncStorage.setItem(storageKeyFavourites, sFavourites);
} catch (e) {
// saving error
Alert.alert('Unable to store favourites')
}
}
const getFavourites = async () => {
try {
const value = await AsyncStorage.getItem(storageKeyFavourites)
if (value !== null) {
checkPageIsFavourite(value, false)
}
} catch (e) {
// err
}
}
As this will be used on multiple pages, I thought it would be good to store the code once in an external file, so I moved it to
PersistenStorage.js
and in the page, added
import * as pStorage from './PersistentStorage.js'
From my main component, I can then call
pStorage.StoreFavourites('somevalue')
and
pStorage.getFavourites()
which work, but I can't find a way for the getFavourites to call functions in the main component (ie which imports the external code)
checkPageIsFavourite(value, false)
can't run as it can't access this function from the external file.
Hope this is clear and is there a way around this? in other words, once the async get has completed, call functions in the main file.

Gridsome mounted method is only running on page reload

I am using the vue mounted lifecyle method to fetch data. The data is stored in algolia. I use the search api to connect and fetch it. The data is only loaded when I refresh the site. It does not run on page navigation.
methods: {
async fetchInventory(data = {}) {
try {
this.isLoading = true;
const result = await index.search("", {hitsPerPage: 12});
this.auctions = result.hits;
this.totalItems = result.nbHits;
this.totalPages = result.nbPages;
this.isLoading = false;
} catch (error) {
this.isLoading = false;
console.log(error);
}
},
},
mounted() {
this.fetchInventory();
}
If this is client side rendering you may need to wait until nextTick OR use earlier/later hook:
mounted() {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
May need to use beforeCreate or created hook if rendering serverside.
Also how is page navigation being done? if you're using navigation API or a library that may be critical to fixing the issue

Provide Inject not working properly in vue 3 composition API

I am working with Vue 3 composition api and am retrieving weather data via async/await fetch and I get a 200 response and the data in the request within the Chrome Dev Tools.
In the component receiving the data and making the call I have a provide method and then I am injecting the data into another output component. The issue is in the inject component. The value for the injected variable is always null and does not update in the Vue Dev Tools so my data is never output to the screen. I went through the docs and the code is pretty much the same but I can't get it to work. Can anyone see an obvious issue?
Receiving Component
setup () {
async function getCurrentWeather () {
const response = await fetch(`${baseWeatherApiUrl}q=${userInput.value}`);
userInput.value = null;
return weatherData.value = await response.json();
}
const returnedWeatherData = reactive(weatherData);
provide('returnedWeatherData', returnedWeatherData);
return {
getCurrentWeather,
userInput,
weatherData
}
}
output component
setup () {
//Provide default of empty object in case no results exist
const weatherData = inject('returnedWeatherData');
console.log(weatherData) //No output even when making a new request to the weather api
return {
weatherData
}
}
As a separate test I tried to provide/inject hardcoded values found in the docs but still geolocation when injected remains null.
provide('geolocation', {
longitude: 90,
latitude: 135
})
const userGeolocation = inject('geolocation')
console.log(userGeolocation) // Nothing logged
return {
weatherData,
userGeolocation
}
In my case it was importing inject from "#vue/runtime-core" instead of "vue".
Of course provide was imported from "vue".
Just leaving here, maybe it's gonna save someone an hour.
The provide-ed argument should be the ref itself (not wrapped in a reactive()):
// Parent.vue
export default {
setup () {
const weatherData = ref()
// ❌
// const returnedWeatherData = reactive(weatherData);
// provide('returnedWeatherData', returnedWeatherData);
// ✅
provide('returnedWeatherData', weatherData);
}
}
And the child component's console.log() in setup() does not automatically get invoked again. You should wrap that call with watchEffect() so that it does get called upon change to the ref:
// Child.vue
import { inject, watchEffect } from 'vue'
export default {
setup () {
const weatherData = inject('returnedWeatherData')
// ❌
//console.log('new weatherData', weatherData.value)
// ✅
watchEffect(() => {
console.log('new weatherData', weatherData.value)
})
}
}
demo

Data Pre-Fetching and State | Vue SSR Guide

Can you tell me what is the usage of created inside the data vue?
created() {
if (this.$store.state.auth.loggedIn) {
if ((this.usersId = this.$store.state.auth.user.results.userId)) {
this.owner = true;
}
}
UserService.getDiscussionDetail(this.$route.params.id).then(
(response) => {
this.discussion = response;
},
() => {
this.success = false;
}
);
},
The created hook runs when the Vue instance is created, just before the virtual DOM nodes are available. This is usually the step where async operations in server side generated apps are processed, such as fetching content and other data that have to be included in the finished DOM tree in the hte static output. The steps in a Vue Lifecycle. are: beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeDestroy, and destroyed.

Which Lifecycle hook after axios get but before DOM render

I'm trying to render my DOM, dependent on some data I'm returning from an axios get. I can't seem to get the timing right. The get is in the created hook, but there is a delay between the get and actually receiving the data. Basically if there is info in seller_id then I need to show the cancel button, otherwise don't. Here is my code:
this is in my created hook
axios.get('https://bc-ship.c9users.io/return_credentials').then(response => {
this.seller_id = response.data.seller_id;
this.selected_marketplace = response.data.marketplace;
this.token = response.data.auth_token;
});
and then this is the logic to show or hide the button. I've tried created, mounted, beforeUpdate, and updated all with no luck. I've also tried $nextTick but I can't get the timing correct. This is what I have currently:
beforeUpdate: function () {
// this.$nextTick(function () {
function sellerIdNotBlank() {
var valid = this.seller_id == '';
return !valid;
}
if(sellerIdNotBlank()){
this.show_cancel_button = true;
}
// })
},
First, it is pointless to get your data from backend and try to sync with Vue.js lifecycle methods. It never works.
Also, you should avoid beforeUpdate lifecycle event. It is often a code smell. beforeUpdate is to be used only when you have some DOM manipulations done manually and you need to adjust them again before Vue.js attempt to re-render.
Further, show_cancel_button is a very good candidate for a computed property. Here is how component will look:
const componentOpts = {
data() {
return {
seller_id: '',
// ... some more fields
};
},
created() {
axios.get('https://bc-ship.c9users.io/return_credentials').then(response => {
this.seller_id = response.data.seller_id;
this.selected_marketplace = response.data.marketplace;
this.token = response.data.auth_token;
});
},
computed: {
show_cancel_button() {
return this.seller_id !== '';
}
}
}