Maurizio Bellemo
Maurizio Bellemo

Reputation: 73

Nuxt3 and Pinia: how to save async API data to the store

I created a Pinia store file to retrieve invoices information from the Node.js API I created available on a public API address

import { mande } from "mande";
import { acceptHMRUpdate, defineStore } from "pinia";

import { useUsersStore } from "./user";

const api = mande("http://xxx.xxx.xxx.xxx/"); // hiding the IP address
const usersStore = useUsersStore();
await usersStore.signIn("[email protected]", "password");
api.options.headers.Authorization = "Bearer " + usersStore.getAccessToken;

export const useInvoicesStore = defineStore("invoices", {
  state: () => ({
    invoices: <any>[] || [],
    invoice: null,
    loading: false,
  }),

  getters: {
    getInvoices: (state) => state.invoices,
    getInvoice: (state) => state.invoice,
  },

  actions: {
    async fetchInvoices() {
      this.invoices = [];
      this.loading = true;
      try {
        this.invoices = (await api.get("invoices")) as any[];
      } catch (error) {
        console.log(error);
      } finally {
        this.loading = false;
      }
    },

    async fetchInvoice(id: string) {
      this.invoice = null;
      this.loading = true;
      try {
        this.invoice = (await api.get(`invoices/${id}`)) as any;
      } catch (error) {
        console.log(error);
      } finally {
        this.loading = false;
      }
    },

    async createInvoice(invoice: any) {
      this.loading = true;
      try {
        await api.post("invoices", invoice);
      } catch (error) {
        console.log(error);
      } finally {
        this.loading = false;
      }
    },

    async updateInvoice(id: string, invoice: any) {
      this.loading = true;
      try {
        await api.patch(`invoices/${id}`, invoice);
      } catch (error) {
        console.log(error);
      } finally {
        this.loading = false;
      }
    },
  },
});

if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useUsersStore, import.meta.hot));
}

I use the store in a Nuxt3 page

<script setup>
const store = useInvoicesStore();

definePageMeta({
  layout: "app",
});

let invoices = [];
await store.fetchInvoices();
invoices = store.getInvoices;
</script>

<template>
  <div>
    <main>
      {{ invoices }}
      <div class="mx-auto max-w-7xl py-6 sm:px-6 lg:px-8">
        <AppInvoiceList :invoices="invoices" />
      </div>
    </main>
  </div>
</template>

I print the entire JSON (invoices) on the UI to understand whether the information is fetched from the server. What happens is that, once I hit reload (F5), for a split second the data appears on the screen. After that, the array is empty and the store as well. How can I correctly save the data coming from the API in the Pinia store?

Upvotes: 2

Views: 4735

Answers (1)

Marc
Marc

Reputation: 5465

This is not the purpose of a Pinia store, it does not give out of the box persisted store states, it is only for providing central state management during the uninterrupted life span of the PWA.

There are two ways I can think of to persist the central state between reloads.

Option 1

Use $subscribe to save Pinia states to the browsers localStorage or indexDB using them as a cache, then on first load check localStorage for anything to restore back to the Pinia state else query the backend, you will need to consider a cache timeout mechanism.

https://pinia.vuejs.org/core-concepts/state.html#subscribing-to-the-state

There is a persisted state pinia plugin available to do this for you:

https://prazdevs.github.io/pinia-plugin-persistedstate/


Option 2

Service worker API - You may not need pinia at all.

https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API

https://developer.mozilla.org/en-US/docs/Web/API/Cache

Upvotes: 3

Related Questions