0

I am trying to use nuxt3s useFetch feature to fetch the pages content. Whenever the slug changes I want to refetch/refresh.

The docs (https://nuxt.com/docs/getting-started/data-fetching) tell me that:

  1. the URL is auto-watched, so a refresh should always happen if my URL changes
  2. that I could use the watch property within useFetch to refresh

Both does not work. I even tried to watch the slug with a watcher and trigger a refresh. No success either. Somehow the whole await useFetch() is just never called anymore...

Here is my code:

<script setup>

const runTimeConfig = useRuntimeConfig()


// Tried to use this, but I don't really understand what that key is for:
// definePageMeta({
//   key: (route) => route.params.slug,
// })

const route = useRoute()
const slug = computed(() => route.params.slug)

const endpoint = `${runTimeConfig.public.API_URL}/wp/v2/pages?slug=${slug.value}`
console.log('endpoint: ', endpoint)

const {
  data: page,
  pending,
  error,
  refresh,
} = await useFetch(endpoint, {
  key: `key-${slug.value}`,
  initialCache: false,
})

console.log('page: ', toRaw(page.value))

Now if I change the slug, I can see that the endpoint log is appearing with the correct URL. But if I log the page, after navigation it logs:page: null...

Also that value is not updated later (first I thought the async await stuff is not working properly).

kissu
  • 40,416
  • 14
  • 65
  • 133
Merc
  • 4,241
  • 8
  • 52
  • 81
  • Try with `() => endpoint ...` in the `useFetch` hook, since it should be a callback that should be called every time. Otherwise, you can probably do a mix of both a watcher + `refresh`. – kissu Aug 14 '23 at 16:50
  • I tried everything. `await useFetch(() => endpoint, {..})`. I tried to define the endpoint as a computed property, as a ref(). Nothing helps. If I log the endpoint, it is updated on a routechange, even the fetch result is logged now, but the content is the same. It seems to be cached or so... (I removed the `key` and `initialCache`). If I add those, my logging of `page` is null again... I really don't understand why... – Merc Aug 15 '23 at 07:47
  • Also: I tried to add `server: false` to finally see a network request. If I then navigate the page is fetched correctly with new slugs. I have no idea why... Why can't I fetch serverside and from then on on route change fetch client side??? – Merc Aug 15 '23 at 07:59
  • I then tried to `generate` and see what happens. If I then added initalCache: false, all the pages were generated correclty and also the navigation worked. When I got back to `nuxi dev`, it still worked even without `server:false`. I have no idea why, I feel very stupid, but it works now... (Maybe because I deleted the directories `.nuxt` and `dist`. This would be the only thing that could have had an effect imo. Anyway. Thanks for all the help! – Merc Aug 15 '23 at 08:41
  • Also another sidenote: @kissu: I don't need `() => endpoint`, my slug and endpoint don't have to be computed nor reactive values. It just works now. Without initialCache, without any specific server settings, without a key. – Merc Aug 15 '23 at 08:45

1 Answers1

0

useFetch refetch dynamic params useRoute().params

~/pages/test-params/[id].vue

<script lang="ts" setup>
const { data } = await useFetch('/api/param', {
  params: useRoute().params,
});
</script>
<template>
  <div>
    <h1>Dynamic Param is: {{ data }}</h1>
    <div v-for="param in 10" :key="param">
      <NuxtLink :to="`/test-params/${param}`">Navigate To {{ param }}</NuxtLink>
    </div>
  </div>
</template>
<style scoped lang="css"></style>
API route ~/server/api/params.get.ts

export default defineEventHandler((event) => {
  const { id } = getQuery(event);
  return id;
});

useFetch refetch dynamic query useRoute().query

<script lang="ts" setup>
//const querySlug = computed(() => useRoute().query.slug ?? 1)  - If you want to add a default;
const querySlug = computed(() => useRoute().query.slug)
const { data: slug } = await useFetch('/api/slug', {
  query: { slug: querySlug },
})
</script>
<template>
  <div>
    <h1>Query</h1>
    <h3>Selected Query: {{ slug }}</h3>
    <div
      v-for="slug in 10"
      :key="slug"
    >
      <NuxtLink :to="`/?slug=${slug}`">Query to {{ slug }}</NuxtLink>
    </div>

    <div style="margin-top: 40px;">
      <NuxtLink to="/">Remove query</NuxtLink>
    </div>
  </div>
</template>
<style scoped lang="css"></style>

API route example ~/server/api/slug.get.ts

export default defineEventHandler((event) => {
  const { slug } = getQuery(event);
  return slug;
});
ReaganM
  • 1,290
  • 1
  • 11
  • Thank you for the lengthy answer! I tried to use the params, but it is just exaclty the same. And as I read useFetch not only watches the params by default but also the URL. Weirdly I don't see the network call either. The first one, maybe not, because it is done on the server (?). It again tells me that the components code is executed on a route change but the fetch request is not sent... – Merc Aug 15 '23 at 07:39
  • This probably works too, but my example above might just do the trick. I don't know why things work now... I added some infos from my side in comments following my question. – Merc Aug 15 '23 at 08:42
  • I'm glad that you figured it out. To support my answer, I'll add some edits as I miss understood your question. My understanding is that you have a dynamic page called `[slug].vue` based on your question on this part `const slug = computed(() => route.params.slug)`. The answer I provided will work on dynamic pages that uses the params `useRoute().params` but it does not work if you use dynamic queries `useRoute().query`. – ReaganM Aug 15 '23 at 13:53
  • I just edited my answer – ReaganM Aug 15 '23 at 14:27
  • @Merc check this to get answer https://stackoverflow.com/questions/74884488/nuxt-3-usefetch-returns-the-error-fetch-failed – Kishan Bhensadadiya Aug 16 '23 at 06:42