logaretm / villus

🏎 A tiny and fast GraphQL client for Vue.js

Home Page:https://villus.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to use in nuxt3 <script setup> with useAsyncData()?

ayalon opened this issue · comments

I tried the villus client with nuxt3 and it basically worked. But I was unsure how to use it together with the new nuxt3 composable "useAsyncData()".

I was using it like that but its a bit a mess because useQuery() already returns reactive data.

<script setup lang="ts">
import {useQuery} from 'villus';
import { AllFilmsDocument } from "@/graphql/operations";

const { data } = await useAsyncData('films', async () => {
  const { data } = await useQuery({
    query: AllFilmsDocument,
  });
  return data.value;
})

const films = data.value.allFilms.films

</script>

Could someone give me some feed if this is correct or how it should / could be improved?

This could be problematic since useQuery uses injections and you can't use injections outside of your setup function. So if it worked for you then it's probably because Nuxt ran the async function during setup, which isn't a good thing to rely on.

Instead you should call the useQuery earlier and use execute inside your asyncData function. I believe something like this should work but I haven't tried it myself:

import {useQuery} from 'villus';
import { AllFilmsDocument } from "@/graphql/operations";

const { execute } = useQuery({
  query: AllFilmsDocument,
  fetchOnMount: false,
});

const { data, pending } = await useAsyncData('films', execute);

Thanks for the example. I think the idea is great but unfortunatly it does not work. If I pass the promise function to userAsyncData() I get back a Proxy Object. It seems that it is not possible to resolve the Promise. I have no clue, wehre the issue is.

Maybe at some time you can try villus in a Nuxt 3 project and add an example.

I made more tests and figured out, that useAsyncData() uses <Suspense> under the hood. From the documentation I got the info, that I need to use await when using useQuery() together with <Suspense>

I adapted the code slightly and now it seems to work even with type hints from the GraphQL Query. But I don't like the additional async method.

<script setup lang="ts">
import { useQuery } from 'villus'
import { AllFilmsDocument } from '~/graphql/operations'

const { execute } = await useQuery({
  query: AllFilmsDocument,
  fetchOnMount: false,
})

const { data } = await useAsyncData('films', async () => {
  const result = await execute()
  return result.data
})

const films = data.value.allFilms.films

Do you have a better proposal @logaretm ?

I think this way you are executing the query twice which isn't ideal, could you skip the await with useQuery and keep everything else as is?

import { useQuery } from 'villus'
import { AllFilmsDocument } from '~/graphql/operations'

const { execute } = useQuery({
  query: AllFilmsDocument,
  fetchOnMount: false,
})

const { data } = await useAsyncData('films', async () => {
  const result = await execute()
  return result.data
})

const films = data.value.allFilms.films

Yeah! This is the right solution i think! Thanks for your valuable help.