Nuxt 3 - useFetch when one query depends on the result of another

859 Views Asked by At

I'm working on a headless Nuxt 3 app and I'm running into an issue with my blog. I think this exposing a gap in my knowledge of how Nuxt 3's fetch utils work. Here's the overview of what I need to happen:

The hero of the blog page is a post feature for the most recent post. This will never change once the page loads. Below the hero is the list of the remaining posts. These posts need to be able to be filtered by category.

So, the intended fetch behavior I need is:

Fetch the featured post once on page load Create a useFetch for the other posts that watches the value of featuredPost and, if its cursor exists, fetches all posts after its cursor (I haven't gotten around to the category filtering part yet).

The error I'm encountering is that, if I hot reload the page via saving my file, everything works as intended. However, if I hard reload, the featured post is not excluded from the list of remaining posts that is fetched. My assumption is that this is because the useFetch for the featured post is running on the server and not again on the client, but I might be wrong about that. Can anyone help me figure out what I'm doing wrong here? I'm attaching my full template for this page. Thanks so much.

<template>
  <div
    v-if="!featuredPending"
  >
    <img
      :src="featuredPost.post.featuredImage?.node?.sourceUrl"
      :alt="featuredPost.post.featuredImage?.node?.altText"
    />
    <div>
      <a href="/">{{
        featuredPost.post.categories?.edges[0].node?.name
      }}</a>
      <span>|</span>
      <span>{{
        featuredPost.post.date
          ? Intl.DateTimeFormat("en-US", {
              month: "short",
              day: "numeric",
              year: "numeric",
            }).format(new Date(featuredPost.post.date))
          : ""
      }}</span>
    </div>
    <h2>{{ featuredPost.post.title }}</h2>
    <a :href="`/blog/${featuredPost.post.slug}`"
      >Continue Reading</a
    >
  </div>
  <divv-if="!pending">
    <div
      v-for="post in posts"
      :index="post.slug"
    >
      <img
        v-if="post.featuredImage"
        :src="post.featuredImage.node.sourceUrl"
        :alt="post.featuredImage.node.altText"
      />
      <div>
        <h3>{{ post.title }}</h3>
        <div>
          <a href="/">{{
            post.categories.edges[0].node.name
          }}</a>
          <span>|</span>
          <time>{{
            Intl.DateTimeFormat("en-US", {
              month: "short",
              day: "numeric",
              year: "numeric",
            }).format(new Date(post.date))
          }}</time>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import gql from "graphql-tag";
import { print } from "graphql";

const config = useRuntimeConfig();

const GET_RECENT_POST = gql`
  query PostsQuery {
    posts(first: 1) {
      edges {
        cursor
        node {
          title(format: RENDERED)
          date
          slug
          featuredImage {
            node {
              altText
              sourceUrl(size: LARGE)
            }
          }
          categories {
            edges {
              node {
                name
              }
            }
          }
        }
      }
    }
  }
`;
const { data: featuredPost, pending: featuredPending } = useFetch(
  config.public.wordpressParentApiUrl,
  {
    key: "featuredPost",
    method: "post",
    body: {
      query: print(GET_RECENT_POST),
    },
    transform(data) {
      return {
        post: data.data.posts.edges[0].node,
        cursor: data.data.posts.edges[0].cursor,
      };
    },
  }
);

const GET_POSTS = gql`
  query PostsQuery($cursor: String) {
    posts(first: 9, after: $cursor) {
      edges {
        cursor
        node {
          title(format: RENDERED)
          content(format: RAW)
          date
          slug
          featuredImage {
            node {
              altText
              sourceUrl(size: LARGE)
            }
          }
          categories {
            edges {
              node {
                name
              }
            }
          }
        }
      }
    }
  }
`;

const { data: posts, pending } = useFetch(config.public.wordpressParentApiUrl, {
  key: "posts",
  method: "post",
  body: {
    query: print(GET_POSTS),
    variables: {
      cursor: featuredPost?.value?.cursor,
    },
  },
  transform(data) {
    return data.data.posts.edges.map((edge) => edge.node);
  },
  watch: [featuredPost],
});
</script>```
0

There are 0 best solutions below