Merc
Merc

Reputation: 4570

How to reuse fetched data in Vue 3 (Nuxt 3)?

I am updating a Nuxt2 project to Nuxt3. Before I used Vuex to share some data across my app. I loaded the navigation structure from an endpoint and could use that information across my components.

Now in Nuxt 3 I thought I could write a composable useNavigation which fetches the navigation and then inside my components I could use that data without needing to fetch over and over again.

Now I run into two problems:

  1. Using async/await in composables seems to be a problem. I have a working example, but I still get warnings, that a composable requires access to the Nuxt instance, which seems to be related with my async/await stuff inside my composable.
  2. I realize that when generating the pages, the page does not wait for the composable to have that data ready. If I instead use useFetch directly in my components/pages, these things are awaited and therefore appear in my generated pages. Things inside my composable are not awaited.

So my main question is: How should I handle data that is used across multiple pages which I don't want to refetch all the time? Should I write at least a mixin and use that to DRY (don't repeat yourself)? Will Nuxt keep a solid cache for such situations so that this does not take too much time?

Or how could I fetch once, make sure that these things are available and then reuse it in my app?

Upvotes: 0

Views: 1180

Answers (1)

Merc
Merc

Reputation: 4570

I think for now I settled with this solution:

As I need the data on a lot of pages (like the navigation), I start fetching the data inside my default.vue layout.

I also have a composable useNavigations.js

export const useNavigation = () => {
  const navs = useState('navs', () => {
    return {
      main: false,
      footer: false,
    }
  })

  const getPageById = (location, id) => {
    if (!navs.value?.[location]) return false
    return toRaw(navs.value[location]).items.find((i) => {
      return i.object_id === id
    })
  }

  const setNavigation = (location, data) => {
    navs.value[location] = data
  }

  return {
    setNavigation,
    getPageById,
    navs,
  }
}

In my default.vue layout I use

// default.vue

const { setNavigation } = useNavigation
//...
setNavigation('main', menu.value)

And in my files where I need the actual data:

// MyComponent.vue

const { navs } = useNavigation()

const menu = computed(() => {
  return navs.value?.main
})

Because I use useState (https://nuxt.com/docs/api/composables/use-state) I think it would be available throughout the app event without using const { navs } = useNavigations()...

Any additional thoughts are very welcome.

Upvotes: 0

Related Questions