dotansimha / dotansimha/graphql-code-generator-community
typescript-vue-urql not using useClientHandle -> causing error with suspense
- Dominant language
- TypeScript
- Stars
- 137
- Forks
- 195
- Avg merge
- 6h 20m
- Merged PRs (30d)
- 16
Description
**Describe the bug**
In the `@graphql-codegen/typescript-vue-urql` plugin, the composition functions refer to the global Urql imported as such: `import * as Urql from '@urql/vue';`. Whilst this can be configured to point to a different instance, there isn't any support for [useClientHandle](https://formidable.com/open-source/urql/docs/api/vue/#useclienthandle).
Why is this important?
When using an async setup function, only one promise can be `await`ed. Therefore, if I generate two queries and call/await on them sequentially, the second will throw the error: `Error: use* functions may only be called during the setup() or other lifecycle hooks.`.
The problem is explained by the urql team [here](https://formidable.com/open-source/urql/docs/basics/vue/#chaining-calls-in-vue-suspense).
**To Reproduce**
```ts
import { useFlightsFromOriginQuery, useFlightsToDestinationQuery } from '../generated/graphql'
export async function useRoutes() {
const originFlights = await useFlightsFromOriginQuery()
const destinationFlights = await useFlightsToDestinationQuery()
return { originFlights, destinationFlights }
```
The error `Error: use* functions may only be called during the setup() or other lifecycle hooks.` is thrown when I am calling from my setup function:
```vue
import { useRoutes } from '../composables/useRoutes'
const responses = await useRoutes()
```
However, this error does not throw if I change the `useRoutes()` query to only run **one** of the queries and not the other. As explained by the urql team, this doesn't necessarily mean two queries generated from this library, it means any two promises in the setup function.
This means we need to create the `clientHandle` in the original setup function and pass it into the `use*` generated query.
Perhaps the easiest way to fix this is to pass down the Urql as an optional parameter to the auto-generated composition function:
https://github.com/dotansimha/graphql-code-generator/blob/988b8b67294e15b7548a554226ee51fce5a4ef4f/packages/plugins/typescript/vue-urql/src/visitor.ts#L73-L74
Which means from my calling code, I can write:
```ts
import { useClientHandle } from '@urql/vue'
import { useFlightsFromOriginQuery, useFlightsToDestinationQuery } from '../generated/graphql'
export async function useRoutes() {
const client = useClientHandle()
const originFlights = await useFlightsFromOriginQuery({}, client)
const destinationFlights = await useFlightsToDestinationQuery({}, client)
return { originFlights, destinationFlights }
```
I looked at this as an alternative:
https://github.com/dotansimha/graphql-code-generator/blob/988b8b67294e15b7548a554226ee51fce5a4ef4f/packages/plugins/typescript/vue-urql/src/visitor.ts#L38
But we can't call `useClientHandle()` until we are actually inside the setup function, meaning the actual composition functions need to change OR we just pass it in from outside.
Perhaps it would be neater if we merged it as an option to the default `UseQueryArgs`, but I'm open to different options.
Sandbox with types generated:
https://codesandbox.io/s/elated-ramanujan-vf6jq?file=/types.ts
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.