Nuxtjs async await in a page doesnt work on page refresh - javascript

Am trying to fetch data in the fetch method of my page using vuex and nuxt js but whenever a person refreshes the page it fails but works when i navigate through nuxt navigation
So in my page i have
fetch ({ store, params }) {
store.dispatch('getJobspecialisims')
},
//IVE ALSO TRIED ASYNC
async asyncData (context) {
await context.store.dispatch('getJobspecialisims');
},
SO in my vuex action i have
async getJobspecialisims({commit}){
await axios.get(process.env.baseUrl+'/job-specialisims').then((res)=>{
commit(types.SET_JOB_SPECIALISIMS, res.data.data)
},(err)=>{
console.log("an error occured ", err);
});
},
Now on my component where am fetching the records
<div>
<li v-for="(specialisim) in $store.getters.jobspecialisims">
<!-DO STUFF HERE->
</li>
The http request is nver sent when a person refreshes the browser
Where am i going wrong?
I would prefer the async await method. I uderstand that it returns a promise but i have no idea on how to know when the promise has resolved. Thepage should always await untill the data has been completely ffetched hence ive called the fetch or asyncdata method in my page
What else do i need to add or amend?

For async actions, you need to put return before dispatch when you call it inside fetch or asyncData:
fetch ({ store, params }) {
// store.dispatch('getJobspecialisims')
return store.dispatch('getJobspecialisims')
},
Source for this answer: Problem: Vuex actions, dispatch from page
Anyway, I still don't understand why you used await with then. If I, I will use async await like this:
async getJobspecialisims({ commit }) {
const res = await axios.get(YOUR_URL);
if (!res.error) {
commit("getJobspecialisims", res.data.data);
} else {
console.log(res.error);
}
}

Related

Why can't I memoize in NextJS' getServerSideProps?

I'm using React + NextJS to display a list of products on a category page.
I can get the products just fine using getServerSideProps, but I don't like that it re-requests the product list on each visit to the same page. I'm trying to memoize a function that gets the list, and while that seems to work (meaning there are no errors thrown), the supposedly memoized function is still called on subsequent visits to the same page.
See the code below, and note that the "get category" console log is shown in the terminal window when I revisit a page, and in Chrome's network tools I see a fetch request made by NextJS.
How can I make it cache the result of my getCategory function so it doesn't keep fetching it?
export async function getServerSideProps(context) {
let config = await import("../../config/config");
let getCategory = memoize(async (url) => {
console.log("getting category");
let response = await axios.get(url);
if ( response.status ) {
return response.data;
} else {
return false;
}
});
let response = await getCategory(`${config.default.apiEndpoint}&cAction=getCTGY&ctgyCode=${context.params.code}`);
if ( response ) {
return {
props: {
category: response
}
};
} else {
return {
props: {
category: null
}
};
}
}
This doesn't work becuase nextjs api routes are "serverless", which means the state that memoize is supposed to remember is destroyed after HTTP call.
The serverless solution is to use a separate service for caching, which is accessible from your api route.
Otherwise, you may need to look at using a custom server.

Cancel async fetch request in React Native using Expo

I have a React Native app that has been built using Expo (v35.0.0). I have a simple async function (loadData()) that runs a fetch (via fetchData()) request to an API that the response is then passed into my redux store:
const loadData = async (id, token) => {
setIsLoading(true);
try {
await dispatch(fetchData(id, token));
} catch (error) {
setHasError(true);
}
setIsLoading(false);
};
useEffect(() => {
loadData(user.client.id, user.token);
}, [user.client.id]);
However, when the user logs out we are presented with the warning: "Can't perform a React state update on an unmounted component", which I understand is because the async request has been cancelled.
I have attempted to implement the AbortController approach (as outlined in this article: https://dev.to/iquirino/react-hook-clean-up-useeffect-24e7), however then we are presented with an error stating AbortConroller is unknown.
I thought that support for AbortConroller would be within Expo now as it was added to React Native back in July last year as part of the v0.60 release.
So, is it possible to implement AbortController within Expo to cancel the async request? If not, how should I go about cancelling the request to avoid the warning (& memory leak)?
Because your dispatch is async, it's possible for it to finish after your component is unmounted.
Inside useEffect you can return a function that you call to cleanup. Here you can set a flag to indicate the component is no longer mounted, and if this flag indicates it's no longer mounted, you can tell it not to update state.
eg.
let mounted = true;
const loadData = async (id, token) => {
setIsLoading(true);
try {
await dispatch(fetchData(id, token));
} catch (error) {
if (mounted) setHasError(true);
}
if (mounted) setIsLoading(false);
};
useEffect(() => {
loadData(user.client.id, user.token);
return () => mounted = false;
}, [user.client.id]);

Await for Action to finish with Async/Await in Nuxt.js (SPA, no SSR)

I'm building an app with Vue and Nuxt w/ Firebase.
I have this Action in the store:
async loadPrev({commit, rootState}, payload) {
try{
let doc = await this.$fireStore.collection(`users/`+ rootState.user.uid + `/preventivi`).doc(payload).get()
commit(`setLoadedPrev`, doc.data())
}
catch(e){
console.log(e)
}
},
In a page component (a dynamic route), I load the information about that precise doc in Firestore via the created() hook:
data(){
return{
prevDetails: {}
}
},
computed: {
...mapGetters({
getLoadedPrev: `prevs/getLoadedPrev`
})
},
methods:{
async loadPrevInfo(){
try{
await this.$store.dispatch(`prevs/loadPrev`, this.$route.params.id)
this.prevDetails = {...this.getLoadedPrev}
}
catch(e){
console.log(e)
}
}
},
created(){
this.loadPrevInfo()
}
Now, everything seems to work, in fact when I go the route that matches the ID of the document in Firestore it loads all the data correctly.
My question is: does the loadPrevInfo() method wait for the dispatch to be completed? I fear that if the data to retrieve are big, the app sets this.prevDetails = {...this.getLoadedPrev} before the dispatch method retrieves all the data from firestore. Do I have to return a promise on the loadPrev action? How?
No, because async/await works the similar way as promise, and code after await will wait until execution of function with await will be finished.
You could also make 'created' async to be able await for loading info.

Vue Refresh page execute multiple axios.post

In App.Vue i have this code:
<script>
import axios from "axios";
import { baseApiUrl, userInfo } from "#/global";
export default {
methods: {
moveToLoginPage() {
localStorage.removeItem(userInfo);
this.$store.commit("setToken", null);
this.$router.push({ path: "/login" });
},
async validateToken() {
const json = localStorage.getItem(userInfo);
const userData = JSON.parse(json);
if (!userData) {
this.moveToLoginPage();
} else {
const url = `${baseApiUrl}/auth/validateToken`;
const resData = await axios.post(url, userData).then(resp => resp.data);
if (!resData) {
this.moveToLoginPage();
}
}
}
},
created() {
this.validateToken();
}
};
</script>
After access the system I go to any other page, and give a refresh. When the page is reloaded, this code snippet from Vue.app is executed to validate the token from localStorage. But before I get the response from the server in validateToken() function, other HTTP.GET requests are executed in the page I has refreshed in function mounted(). I would like the validateToken() function to fully execute before the other page's mounted() function is executed.
You can use async/await like so:
async created(){
await this.validateToken();
}
This will prevent the create lifecycle hook from completing until the validateToken returns a response
I am assuming you have a router-view in your App.vue file.
You can keep a flag / variable for your async data and then load the router-view only if that data is available.
<template>
<router-view v-if="data"></router-view>
</template>
This way, your inner children aren't even loaded till the time your async data is available.
This answer is just the same comment I made on the question above but for future people to come.

Axios unable get data from API in NativeScript

I have created a local API with Laravel. I have tried use Postman to run this API which is return me data, but when i using Axios in NativesScript Javascript file, it doesn't return the data nor error message.
I have tried use Async and Await in the function but still return nothing.
import axios from 'axios'
export default class Service {
async testing(){
await axios.get('https://app.app/api/testing')
.then(res => {
console.log(res.data);
})
.catch(function(error) {
console.log(error);
});
}
}
I expect the output is 1, but it come out with "", and i found out that it never go to the API (I have put debug point, it no trigger.), but the Postman work just fine (same url), it trigger the debug point and it does return me value 1.
Thank you.
async/await should be wrapped inside try/catch block.
try {
const result = await axios.get('https://app.app/api/testing');
console.log(result)
} catch(err) {
console.log(err);
}

Categories