amrnn90 / breeze-nuxt

An application / authentication starter kit frontend in Nuxt3 for Laravel Breeze.
MIT License
198 stars 33 forks source link

useLarafetch with async functions inside other composable #19

Closed carlosvaldesweb closed 1 year ago

carlosvaldesweb commented 1 year ago

Hello, i'm trying to use "useLarafetch" inside of my composable called "useDocuments", i'm trying to get documents from laravel in lazy mode, to show skeletons while documents loads. The function is called like it doesn't be async function, so i can't use loadingDocuments var because it is always false, any suggestion? Is an error that i can't see in useLarafetch? Maybe is running always in ssr? If i use useLarafetch directly in setup funcion it works, but when i try to use in my composable with lazy option, it works like ssr.

useDocuments.ts

export const useDocuments = () => {
  const documents = useState<Pagination<Document> | null>(
    "documents",
    () => null,
  );

  const document = useState<Document | null | undefined>(
    "document",
    () => null,
  );
  const isEditing = useState<boolean>("isEditing", () => false);
  const loadingDocuments = useState<boolean>("loadingDocuments", () => false);

  const getDocuments = async () => {
    loadingDocuments.value = true;
    try {
      const { data, pending } = await useLarafetch<Pagination<Document>>(
        "/documents",
        {
          lazy: true,
        },
      );
      loadingDocuments.value = false;
      documents.value = data.value;
      return { data, pending };
    } catch (error) {
      console.log(error);
    }
  };

documents.vue

const { getDocument, documents, getDocuments, isEditing, loadingDocuments } =
  useDocuments();
await getDocuments();
amrnn90 commented 1 year ago

Not really sure what you are trying to do, why not just do this?

// useDocuments.ts
export const useDocuments = async () => {
  const { data: documents, ...rest } = await useLarafetch("/documents", {
    lazy: true,
  });

  return {
    documents,
    ...rest,
  };
};
// documents.vue
<script setup lang="ts">
const {documents, pending} = await useDocuments();
</script>

<template>
  <div>
    <div v-if="pending">Loading...</div>
    <pre v-else>{{ documents }}</pre>
  </div>
</template>
carlosvaldesweb commented 1 year ago

I want to save the documents and function in composable to use in different components as state. I.e I need to reload documents when user add new document in createDocument.vue component or when edit the title in editDocument component. Also I have a paginated documents. I think to call to getDocuments with the new cursor to push new documents in infinite scroll

amrnn90 commented 1 year ago

In this case I would suggest using pinia and calling $larafetch directly, maybe something like this:

// useDocuments.ts

import { defineStore } from "pinia";

export const useDocuments = defineStore("documents", () => {
  const documents = ref<undefined | null | any[]>(undefined);
  let page = ref(1);
  const pending = ref(false);

  async function getDocuments() {
    pending.value = true;
    documents.value = documents.value ?? null;
    const newDocs = await $larafetch(`/documents?page=${page.value}`);
    pending.value = false;
    documents.value = [...(documents.value || []), ...newDocs];
  }

  async function nextPage() {
    page.value++;
    return getDocuments();
  }

  return {
    documents,
    page,
    nextPage,
    pending,
  };
});
// documents.vue
<script setup lang="ts">
const docStore = useDocuments();
if (docStore.documents === undefined) {
   await docStore.nextPage();
}
</script>

<template>
  <div>
    <pre v-if="docStore.documents">{{ docStore.documents }}</pre>
    <div v-if="docStore.pending">Loading...</div>
    <button @click="() => docStore.nextPage()">Get</button>
  </div>
</template>

Hope this helps you out, I am closing this since it is not directly related to this repo.

amrnn90 commented 1 year ago

BTW if you are looking for a full-featured solution to this kind of problem then you might want to consider using TanStack Query, they have an example of making it work with Nuxt.