Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

(urql/vue) - provide the client as a ref so changes are observed (#2047)

* provide the client as a ref so changes are observed

* make useClient return a Ref of a client

* update tests

authored by

Jovi De Croock and committed by
GitHub
9beb07e6 c4d95f07

+38 -27
+6
.changeset/gold-geese-fly.md
··· 1 + --- 2 + '@urql/vue': minor 3 + --- 4 + 5 + Provide the client as a ref so it can observe changes. This change is potentially breaking for 6 + anyone using the `useClient` import as it will now return a `Ref<Client>` rather than a `Client`
+12 -12
packages/vue-urql/src/useClient.ts
··· 1 - import { App, getCurrentInstance, inject, provide, Ref, isRef } from 'vue'; 1 + import { App, getCurrentInstance, inject, provide, Ref, isRef, ref } from 'vue'; 2 2 import { Client, ClientOptions } from '@urql/core'; 3 3 4 4 export function provideClient(opts: ClientOptions | Client | Ref<Client>) { 5 - let client: Client; 6 - if (isRef(opts)) { 7 - client = opts.value; 5 + let client: Ref<Client>; 6 + if (!isRef(opts)) { 7 + client = ref(opts instanceof Client ? opts : new Client(opts)); 8 8 } else { 9 - client = opts instanceof Client ? opts : new Client(opts); 9 + client = opts; 10 10 } 11 11 12 12 provide('$urql', client); 13 - return client; 13 + return client.value; 14 14 } 15 15 16 16 export function install(app: App, opts: ClientOptions | Client | Ref<Client>) { 17 - let client: Client; 18 - if (isRef(opts)) { 19 - client = opts.value; 17 + let client: Ref<Client>; 18 + if (!isRef(opts)) { 19 + client = ref(opts instanceof Client ? opts : new Client(opts)); 20 20 } else { 21 - client = opts instanceof Client ? opts : new Client(opts); 21 + client = opts; 22 22 } 23 23 app.provide('$urql', client); 24 24 } 25 25 26 - export function useClient(): Client { 26 + export function useClient(): Ref<Client> { 27 27 if (process.env.NODE_ENV !== 'production' && !getCurrentInstance()) { 28 28 throw new Error( 29 29 'use* functions may only be called during the `setup()` or other lifecycle hooks.' 30 30 ); 31 31 } 32 32 33 - const client = inject('$urql') as Client; 33 + const client = inject('$urql') as Ref<Client>; 34 34 if (process.env.NODE_ENV !== 'production' && !client) { 35 35 throw new Error( 36 36 'No urql Client was provided. Did you forget to install the plugin or call `provideClient` in a parent?'
+1 -1
packages/vue-urql/src/useClientHandle.ts
··· 47 47 }); 48 48 49 49 const handle: ClientHandle = { 50 - client, 50 + client: client.value, 51 51 52 52 useQuery<T = any, V = object>( 53 53 args: UseQueryArgs<T, V>
+3 -2
packages/vue-urql/src/useMutation.test.ts
··· 1 + import { reactive, ref } from 'vue'; 2 + 1 3 jest.mock('./useClient.ts', () => ({ 2 4 __esModule: true, 3 5 ...jest.requireActual('./useClient.ts'), 4 - useClient: () => client, 6 + useClient: () => ref(client), 5 7 })); 6 8 7 9 import { makeSubject } from 'wonka'; 8 10 import { createClient, gql } from '@urql/core'; 9 11 import { useMutation } from './useMutation'; 10 - import { reactive } from 'vue'; 11 12 12 13 const client = createClient({ url: '/graphql', exchanges: [] }); 13 14
+2 -2
packages/vue-urql/src/useMutation.ts
··· 40 40 41 41 export function callUseMutation<T = any, V = any>( 42 42 query: TypedDocumentNode<T, V> | DocumentNode | string, 43 - client: Client = useClient() 43 + client: Ref<Client> = useClient() 44 44 ): UseMutationResponse<T, V> { 45 45 const data: Ref<T | undefined> = ref(); 46 46 const stale: Ref<boolean> = ref(false); ··· 63 63 fetching.value = true; 64 64 65 65 return pipe( 66 - client.executeMutation<T, V>( 66 + client.value.executeMutation<T, V>( 67 67 createRequest<T, V>(query, unwrapPossibleProxy<V>(variables)), 68 68 context || {} 69 69 ),
+3 -2
packages/vue-urql/src/useQuery.test.ts
··· 1 + import { nextTick, reactive, ref } from 'vue'; 2 + 1 3 jest.mock('./useClient.ts', () => ({ 2 4 __esModule: true, 3 5 ...jest.requireActual('./useClient.ts'), 4 - useClient: () => client, 6 + useClient: () => ref(client), 5 7 })); 6 8 7 9 import { pipe, makeSubject, fromValue, delay } from 'wonka'; 8 10 import { createClient } from '@urql/core'; 9 11 import { useQuery } from './useQuery'; 10 - import { nextTick, ref, reactive } from 'vue'; 11 12 12 13 const client = createClient({ url: '/graphql', exchanges: [] }); 13 14
+3 -3
packages/vue-urql/src/useQuery.ts
··· 63 63 64 64 export function callUseQuery<T = any, V = object>( 65 65 _args: UseQueryArgs<T, V>, 66 - client: Client = useClient(), 66 + client: Ref<Client> = useClient(), 67 67 stops: WatchStopHandle[] = [] 68 68 ): UseQueryResponse<T, V> { 69 69 const args = reactive(_args); ··· 103 103 stops.push( 104 104 watchEffect(() => { 105 105 source.value = !isPaused.value 106 - ? client.executeQuery<T, V>(request.value, { 106 + ? client.value.executeQuery<T, V>(request.value, { 107 107 requestPolicy: args.requestPolicy, 108 108 ...args.context, 109 109 }) ··· 120 120 fetching, 121 121 isPaused, 122 122 executeQuery(opts?: Partial<OperationContext>): UseQueryResponse<T, V> { 123 - source.value = client.executeQuery<T, V>(request.value, { 123 + source.value = client.value.executeQuery<T, V>(request.value, { 124 124 requestPolicy: args.requestPolicy, 125 125 ...args.context, 126 126 ...opts,
+3 -2
packages/vue-urql/src/useSubscription.test.ts
··· 1 + import { nextTick, reactive, ref } from 'vue'; 2 + 1 3 jest.mock('./useClient.ts', () => ({ 2 4 __esModule: true, 3 5 ...jest.requireActual('./useClient.ts'), 4 - useClient: () => client, 6 + useClient: () => ref(client), 5 7 })); 6 8 7 9 import { makeSubject } from 'wonka'; 8 10 import { createClient } from '@urql/core'; 9 11 import { useSubscription } from './useSubscription'; 10 - import { nextTick, reactive, ref } from 'vue'; 11 12 12 13 const client = createClient({ url: '/graphql', exchanges: [] }); 13 14
+5 -3
packages/vue-urql/src/useSubscription.ts
··· 64 64 export function callUseSubscription<T = any, R = T, V = object>( 65 65 _args: UseSubscriptionArgs<T, V>, 66 66 handler?: SubscriptionHandlerArg<T, R>, 67 - client: Client = useClient(), 67 + client: Ref<Client> = useClient(), 68 68 stops: WatchStopHandle[] = [] 69 69 ): UseSubscriptionResponse<T, R, V> { 70 70 const args = reactive(_args); ··· 106 106 stops.push( 107 107 watchEffect(() => { 108 108 source.value = !isPaused.value 109 - ? client.executeSubscription<T, V>(request.value, { ...args.context }) 109 + ? client.value.executeSubscription<T, V>(request.value, { 110 + ...args.context, 111 + }) 110 112 : undefined; 111 113 }, watchOptions) 112 114 ); ··· 154 156 executeSubscription( 155 157 opts?: Partial<OperationContext> 156 158 ): UseSubscriptionState<T, R, V> { 157 - source.value = client.executeSubscription<T, V>(request.value, { 159 + source.value = client.value.executeSubscription<T, V>(request.value, { 158 160 ...args.context, 159 161 ...opts, 160 162 });