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

+6
.changeset/gold-geese-fly.md
···
+
---
+
'@urql/vue': minor
+
---
+
+
Provide the client as a ref so it can observe changes. This change is potentially breaking for
+
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
···
-
import { App, getCurrentInstance, inject, provide, Ref, isRef } from 'vue';
+
import { App, getCurrentInstance, inject, provide, Ref, isRef, ref } from 'vue';
import { Client, ClientOptions } from '@urql/core';
export function provideClient(opts: ClientOptions | Client | Ref<Client>) {
-
let client: Client;
-
if (isRef(opts)) {
-
client = opts.value;
+
let client: Ref<Client>;
+
if (!isRef(opts)) {
+
client = ref(opts instanceof Client ? opts : new Client(opts));
} else {
-
client = opts instanceof Client ? opts : new Client(opts);
+
client = opts;
}
provide('$urql', client);
-
return client;
+
return client.value;
}
export function install(app: App, opts: ClientOptions | Client | Ref<Client>) {
-
let client: Client;
-
if (isRef(opts)) {
-
client = opts.value;
+
let client: Ref<Client>;
+
if (!isRef(opts)) {
+
client = ref(opts instanceof Client ? opts : new Client(opts));
} else {
-
client = opts instanceof Client ? opts : new Client(opts);
+
client = opts;
}
app.provide('$urql', client);
}
-
export function useClient(): Client {
+
export function useClient(): Ref<Client> {
if (process.env.NODE_ENV !== 'production' && !getCurrentInstance()) {
throw new Error(
'use* functions may only be called during the `setup()` or other lifecycle hooks.'
);
}
-
const client = inject('$urql') as Client;
+
const client = inject('$urql') as Ref<Client>;
if (process.env.NODE_ENV !== 'production' && !client) {
throw new Error(
'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
···
});
const handle: ClientHandle = {
-
client,
+
client: client.value,
useQuery<T = any, V = object>(
args: UseQueryArgs<T, V>
+3 -2
packages/vue-urql/src/useMutation.test.ts
···
+
import { reactive, ref } from 'vue';
+
jest.mock('./useClient.ts', () => ({
__esModule: true,
...jest.requireActual('./useClient.ts'),
-
useClient: () => client,
+
useClient: () => ref(client),
}));
import { makeSubject } from 'wonka';
import { createClient, gql } from '@urql/core';
import { useMutation } from './useMutation';
-
import { reactive } from 'vue';
const client = createClient({ url: '/graphql', exchanges: [] });
+2 -2
packages/vue-urql/src/useMutation.ts
···
export function callUseMutation<T = any, V = any>(
query: TypedDocumentNode<T, V> | DocumentNode | string,
-
client: Client = useClient()
+
client: Ref<Client> = useClient()
): UseMutationResponse<T, V> {
const data: Ref<T | undefined> = ref();
const stale: Ref<boolean> = ref(false);
···
fetching.value = true;
return pipe(
-
client.executeMutation<T, V>(
+
client.value.executeMutation<T, V>(
createRequest<T, V>(query, unwrapPossibleProxy<V>(variables)),
context || {}
),
+3 -2
packages/vue-urql/src/useQuery.test.ts
···
+
import { nextTick, reactive, ref } from 'vue';
+
jest.mock('./useClient.ts', () => ({
__esModule: true,
...jest.requireActual('./useClient.ts'),
-
useClient: () => client,
+
useClient: () => ref(client),
}));
import { pipe, makeSubject, fromValue, delay } from 'wonka';
import { createClient } from '@urql/core';
import { useQuery } from './useQuery';
-
import { nextTick, ref, reactive } from 'vue';
const client = createClient({ url: '/graphql', exchanges: [] });
+3 -3
packages/vue-urql/src/useQuery.ts
···
export function callUseQuery<T = any, V = object>(
_args: UseQueryArgs<T, V>,
-
client: Client = useClient(),
+
client: Ref<Client> = useClient(),
stops: WatchStopHandle[] = []
): UseQueryResponse<T, V> {
const args = reactive(_args);
···
stops.push(
watchEffect(() => {
source.value = !isPaused.value
-
? client.executeQuery<T, V>(request.value, {
+
? client.value.executeQuery<T, V>(request.value, {
requestPolicy: args.requestPolicy,
...args.context,
})
···
fetching,
isPaused,
executeQuery(opts?: Partial<OperationContext>): UseQueryResponse<T, V> {
-
source.value = client.executeQuery<T, V>(request.value, {
+
source.value = client.value.executeQuery<T, V>(request.value, {
requestPolicy: args.requestPolicy,
...args.context,
...opts,
+3 -2
packages/vue-urql/src/useSubscription.test.ts
···
+
import { nextTick, reactive, ref } from 'vue';
+
jest.mock('./useClient.ts', () => ({
__esModule: true,
...jest.requireActual('./useClient.ts'),
-
useClient: () => client,
+
useClient: () => ref(client),
}));
import { makeSubject } from 'wonka';
import { createClient } from '@urql/core';
import { useSubscription } from './useSubscription';
-
import { nextTick, reactive, ref } from 'vue';
const client = createClient({ url: '/graphql', exchanges: [] });
+5 -3
packages/vue-urql/src/useSubscription.ts
···
export function callUseSubscription<T = any, R = T, V = object>(
_args: UseSubscriptionArgs<T, V>,
handler?: SubscriptionHandlerArg<T, R>,
-
client: Client = useClient(),
+
client: Ref<Client> = useClient(),
stops: WatchStopHandle[] = []
): UseSubscriptionResponse<T, R, V> {
const args = reactive(_args);
···
stops.push(
watchEffect(() => {
source.value = !isPaused.value
-
? client.executeSubscription<T, V>(request.value, { ...args.context })
+
? client.value.executeSubscription<T, V>(request.value, {
+
...args.context,
+
})
: undefined;
}, watchOptions)
);
···
executeSubscription(
opts?: Partial<OperationContext>
): UseSubscriptionState<T, R, V> {
-
source.value = client.executeSubscription<T, V>(request.value, {
+
source.value = client.value.executeSubscription<T, V>(request.value, {
...args.context,
...opts,
});