dotansimha / dotansimha/graphql-code-generator-community

typescript-vue-urql not using useClientHandle -> causing error with suspense

Open
#136 2 comments 4 reactions 0 assignees View on GitHub
help wanted
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.