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

Configure Feed

Select the types of activity you want to include in your feed.

feat:(vue): Optional injection key to allow multiple clients (#3858)

authored by

Albert and committed by
GitHub
773cae7c 71f049c6

+57 -9
+5
.changeset/some-bushes-smash.md
··· 1 + --- 2 + '@urql/vue': minor 3 + --- 4 + 5 + Optional custom injection key support for `provideClient`, `install`, `useClient`, and `useClientHandle`. Multiple clients can be provided and consumed under different keys; default key remains `'$urql'` for backward compatibility.
+35
packages/vue-urql/src/useClient.test.ts
··· 26 26 mount(TestComponent); 27 27 }); 28 28 29 + it('provides client with custom key to current component instance', async () => { 30 + const CUSTOM_KEY = 'custom-key'; 31 + const SUSPENSE_CLIENT = true; 32 + const TestComponent = defineComponent({ 33 + setup() { 34 + provideClient( 35 + new Client({ 36 + url: 'test', 37 + suspense: SUSPENSE_CLIENT, 38 + exchanges: [], 39 + }) 40 + ); 41 + 42 + const client = useClient(); 43 + expect(client).toBeDefined(); 44 + expect(client.value.suspense).toBe(SUSPENSE_CLIENT); 45 + 46 + provideClient( 47 + new Client({ 48 + url: 'test', 49 + suspense: !SUSPENSE_CLIENT, 50 + exchanges: [], 51 + }), 52 + CUSTOM_KEY 53 + ); 54 + const customClient = useClient(CUSTOM_KEY); 55 + expect(customClient).toBeDefined(); 56 + expect(customClient.value.suspense).toBe(!SUSPENSE_CLIENT); 57 + return null; 58 + }, 59 + }); 60 + 61 + mount(TestComponent); 62 + }); 63 + 29 64 it('provides client to child components via provide/inject', async () => { 30 65 const ChildComponent = defineComponent({ 31 66 setup() {
+14 -6
packages/vue-urql/src/useClient.ts
··· 3 3 import type { ClientOptions } from '@urql/core'; 4 4 import { Client } from '@urql/core'; 5 5 6 + export const DEFAULT_KEY = '$urql'; 6 7 // WeakMap to store client instances as fallback when client is provided and used in the same component 7 8 const clientsPerScope = new WeakMap<{}, Ref<Client>>(); 8 9 ··· 32 33 * </script> 33 34 * ``` 34 35 */ 35 - export function provideClient(opts: ClientOptions | Client | Ref<Client>) { 36 + export function provideClient( 37 + opts: ClientOptions | Client | Ref<Client>, 38 + key: string = DEFAULT_KEY 39 + ) { 36 40 let client: Ref<Client>; 37 41 if (!isRef(opts)) { 38 42 client = shallowRef(opts instanceof Client ? opts : new Client(opts)); ··· 45 49 clientsPerScope.set(scope, client); 46 50 } 47 51 48 - provide('$urql', client); 52 + provide(key, client); 49 53 return client.value; 50 54 } 51 55 ··· 74 78 * }); 75 79 * ``` 76 80 */ 77 - export function install(app: App, opts: ClientOptions | Client | Ref<Client>) { 81 + export function install( 82 + app: App, 83 + opts: ClientOptions | Client | Ref<Client>, 84 + key: string = DEFAULT_KEY 85 + ) { 78 86 let client: Ref<Client>; 79 87 if (!isRef(opts)) { 80 88 client = shallowRef(opts instanceof Client ? opts : new Client(opts)); 81 89 } else { 82 90 client = opts; 83 91 } 84 - app.provide('$urql', client); 92 + app.provide(key, client); 85 93 } 86 94 87 95 /** Returns a provided reactive ref object of a {@link Client}. ··· 96 104 * In development, if `useClient` is called outside of a reactive context 97 105 * or no {@link Client} was provided, an error will be thrown. 98 106 */ 99 - export function useClient(): Ref<Client> { 107 + export function useClient(key: string = DEFAULT_KEY): Ref<Client> { 100 108 const scope = getCurrentScope(); 101 109 if (process.env.NODE_ENV !== 'production' && !scope) { 102 110 throw new Error( ··· 104 112 ); 105 113 } 106 114 107 - let client = inject('$urql') as Ref<Client> | undefined; 115 + let client = inject(key) as Ref<Client> | undefined; 108 116 if (!client) { 109 117 client = clientsPerScope.get(scope!); 110 118 }
+3 -3
packages/vue-urql/src/useClientHandle.ts
··· 2 2 import type { WatchStopHandle } from 'vue'; 3 3 import { getCurrentInstance, onMounted, onBeforeUnmount } from 'vue'; 4 4 5 - import { useClient } from './useClient'; 5 + import { useClient, DEFAULT_KEY } from './useClient'; 6 6 7 7 import type { UseQueryArgs, UseQueryResponse } from './useQuery'; 8 8 import { callUseQuery } from './useQuery'; ··· 126 126 * }; 127 127 * ``` 128 128 */ 129 - export function useClientHandle(): ClientHandle { 130 - const client = useClient(); 129 + export function useClientHandle(key: string = DEFAULT_KEY): ClientHandle { 130 + const client = useClient(key); 131 131 const stops: WatchStopHandle[] = []; 132 132 133 133 onBeforeUnmount(() => {