I have created pinia store as position API (setup). I have loadWidgets async function which I want to await outside of store, and then get widgets property from store (after it's been populated). It seems like .then() doesn't do the work, it doesn't actually await for this function to be finished. I need some better approach to this, any modification would work.
Here's dashboard.js file (store) content:
import { defineStore } from "pinia";
import { useFetch } from "#app";
import { useAuthStore } from "./auth";
const baseUrl = import.meta.env.VITE_API_KEY + "/hr/widgets/dashboard";
export const useDashboardStore = defineStore("dashboard", () => {
const authStore = useAuthStore();
const { getToken } = authStore;
const widgets = ref([]);
const fetchedWidgets = ref(false);
async function loadWidgets() {
return useFetch(baseUrl + "/list/get", {
headers: {
Accept: "application/json",
Authorization: "Bearer " + getToken,
},
onResponse({ request, response, options }) {
widgets.value = response._data;
fetchedWidgets.value = true;
},
onResponseError({ request, response, options }) {
throw showError({
statusCode: 401,
statusMessage: "Error: - " + response._data,
fatal: true,
});
},
});
}
return {
widgets,
loadWidgets,
fetchedWidgets,
};
});
Here's my ponent script where I try to use this store:
<script setup>
import { ref } from "vue";
import { useDashboardStore } from "~/stores/dashboard";
import { useCandidatesStore } from "~/stores/candidates";
const props = defineProps({
page: {
type: String,
required: true,
},
});
const dashboardStore = useDashboardStore();
const candidatesStore = useCandidatesStore();
onMounted(async () => {
await getWidgets().then((values) => {
mapWidgetsData(values);
});
});
const getWidgets = async () => {
switch (props.page) {
case "dashboard": {
const { loadWidgets, widgets, fetchedWidgets } = dashboardStore;
if (!fetchedWidgets) {
return await loadWidgets().then(() => {
return widgets.value;
});
}
return widgets.value;
}
case "employees": {
const { loadWidgets, widgets, fetchedWidgets } = candidatesStore;
// Here will be done the same, just using diferent store. Not implemented yet
}
}
};
const mapWidgetsData = function (values) {
var itemsData = values.data;
layout.value = [];
itemsData.forEach((value, key) => {
let item = JSON.parse(value.position);
item.i = value.id;
item.type = value.type;
layout.value.push(item);
});
index.value = values.last_index + 1;
};
</script>
I am using Nuxt 3, Vue 3 and Pinia store and position API. I tried wrapping this load function in Promise, but I always had some errors. With this code, the error I'm getting is
Uncaught (in promise) TypeError: values is undefined
because the return value of getWidgets function is undefined, because it doesn't wait for loadWidgets to finish API call and populate widgets field, but returns the widgets right away (I assume). I want it to wait for widgets to be populated with the value from response and then to continue execution.
I have created pinia store as position API (setup). I have loadWidgets async function which I want to await outside of store, and then get widgets property from store (after it's been populated). It seems like .then() doesn't do the work, it doesn't actually await for this function to be finished. I need some better approach to this, any modification would work.
Here's dashboard.js file (store) content:
import { defineStore } from "pinia";
import { useFetch } from "#app";
import { useAuthStore } from "./auth";
const baseUrl = import.meta.env.VITE_API_KEY + "/hr/widgets/dashboard";
export const useDashboardStore = defineStore("dashboard", () => {
const authStore = useAuthStore();
const { getToken } = authStore;
const widgets = ref([]);
const fetchedWidgets = ref(false);
async function loadWidgets() {
return useFetch(baseUrl + "/list/get", {
headers: {
Accept: "application/json",
Authorization: "Bearer " + getToken,
},
onResponse({ request, response, options }) {
widgets.value = response._data;
fetchedWidgets.value = true;
},
onResponseError({ request, response, options }) {
throw showError({
statusCode: 401,
statusMessage: "Error: - " + response._data,
fatal: true,
});
},
});
}
return {
widgets,
loadWidgets,
fetchedWidgets,
};
});
Here's my ponent script where I try to use this store:
<script setup>
import { ref } from "vue";
import { useDashboardStore } from "~/stores/dashboard";
import { useCandidatesStore } from "~/stores/candidates";
const props = defineProps({
page: {
type: String,
required: true,
},
});
const dashboardStore = useDashboardStore();
const candidatesStore = useCandidatesStore();
onMounted(async () => {
await getWidgets().then((values) => {
mapWidgetsData(values);
});
});
const getWidgets = async () => {
switch (props.page) {
case "dashboard": {
const { loadWidgets, widgets, fetchedWidgets } = dashboardStore;
if (!fetchedWidgets) {
return await loadWidgets().then(() => {
return widgets.value;
});
}
return widgets.value;
}
case "employees": {
const { loadWidgets, widgets, fetchedWidgets } = candidatesStore;
// Here will be done the same, just using diferent store. Not implemented yet
}
}
};
const mapWidgetsData = function (values) {
var itemsData = values.data;
layout.value = [];
itemsData.forEach((value, key) => {
let item = JSON.parse(value.position);
item.i = value.id;
item.type = value.type;
layout.value.push(item);
});
index.value = values.last_index + 1;
};
</script>
I am using Nuxt 3, Vue 3 and Pinia store and position API. I tried wrapping this load function in Promise, but I always had some errors. With this code, the error I'm getting is
Uncaught (in promise) TypeError: values is undefined
because the return value of getWidgets function is undefined, because it doesn't wait for loadWidgets to finish API call and populate widgets field, but returns the widgets right away (I assume). I want it to wait for widgets to be populated with the value from response and then to continue execution.
-
1
you've probably confused yourself with
await somePromise.then( .... )
... and not returning what you think you're returning ... either use async/await OR use .then ... you hardly ever need to use.then
inside anasync
function – Jaromanda X Commented Aug 8, 2023 at 22:49
1 Answer
Reset to default 4The issue here was that I was extracting the ref variables from the store the same way as functions, which is not allowed in Pinia, because then they lose reactivity. I should have accessed them like
dashboardStore.widgets
instead of
const { widgets } = dashboardStore;
The same for fetchedWidgets, it's bool variable.