#useAsyncData with pinia

1 messages · Page 1 of 1 (latest)

robust latch
#

I was reading through the documentation on useAsyncData and I noticed that it mentioned:

useAsyncData is for fetching and caching data, not triggering side effects like calling Pinia actions, as this can cause unintended behavior such as repeated executions with nullish values. If you need to trigger side effects, use the callOnce utility to do so.
with the following example:

const offersStore = useOffersStore()

// you can't do this
await useAsyncData(() => offersStore.getOffer(route.params.slug))

I'm curious if you could provide more explanation on this... Specifically, if the presence of a key/or a single fetch without any computed url changes things.
In my case, I don't want to the call to block the route e.g.,

const userStore = useUserStore()

await useAsyncData('offers', store.getUser, {
  lazy: true
})

I'm aware I could move the logic out of the store and leverage the built-in cache from useFetch / useAsyncData.
Would something like this work as well?

const useUserStore = defineStore('use', () => {
  const user = ref<User>()

  function fetchUser() {
    // useFetch instead of $fetch
    const { data } = useFetch('', { lazy: true })
    user.value = data.value
  }
})

// script setup
await callOnce(async () => {
  await store.fetchUser()
})
Nuxt

Nuxt provides composables to handle data fetching within your application.

weak solsticeBOT
#

Hi @robust latch. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

You're asking about the proper way to use useAsyncData with Pinia stores in Nuxt, which is a great question since this can be a source of confusion.

Why not to use useAsyncData with Pinia actions

The documentation warns against using useAsyncData with Pinia actions because:

  1. useAsyncData is designed specifically for data fetching and caching, not for triggering side effects
  2. If a Pinia action returns undefined or a nullish value, useAsyncData may re-execute, causing repeated calls to the same action
  3. This can lead to unintended behavior in your application

Using callOnce instead

Your second approach using callOnce is the recommended way to handle this scenario. The callOnce utility was specifically designed to execute code only once during:

  • Server-side rendering (but not hydration)
  • Client-side navigation
const useUserStore = defineStore('use', () => {
  const user = ref<User>()

  function fetchUser() {
    // useFetch instead of $fetch
    const { data } = useFetch('', { lazy: true })
    user.value = data.value
  }
})

// script setup
await callOnce(async () => {
  await store.fetchUser()
})

This approach is correct because:

  1. callOnce ensures your store action is only called once during rendering
  2. Inside your store, using useFetch properly handles the data fetching with Nuxt's caching mechanism
  3. The lazy: true option prevents blocking navigation

As mentioned in the documentation, callOnce is specifically useful in combination with Pinia to call store actions Docs > Api > Utils > callOnce.

Alternative approach

If you want to keep your data fetching logic in your component rather than the store, you could also do:

// In your component
const userStore = useUserStore()
#

const { data } = await useFetch('/api/user', {
lazy: true,
transform: (data) => {
// Update store after fetching
userStore.setUser(data)
return data
}
})


This way, you're using `useFetch` for what it's designed for (data fetching) and then updating your store as a side effect through the transform function.

Remember that `useFetch` is essentially a wrapper around `useAsyncData` and `$fetch`, providing a cleaner API for the most common use case [Docs > Getting-started > Data Fetching](<https://nuxt.com/docs/getting-started/data-fetching>).
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------