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.

fix(vue): Ensure that source is updated atomically (#3231)

authored by

Phil Pluckthun and committed by
GitHub
f94f33fe 81ce770b

+103 -41
+5
.changeset/hungry-cars-hide.md
··· 1 + --- 2 + '@urql/vue': patch 3 + --- 4 + 5 + Prevent multiple operations being executed in a row when multiple inputs change simultaneously (e.g. `isPaused` and query inputs)
+36 -21
packages/vue-urql/src/useQuery.ts
··· 1 1 /* eslint-disable react-hooks/rules-of-hooks */ 2 2 3 - import { WatchStopHandle, Ref, ref, watchEffect, reactive, isRef } from 'vue'; 3 + import { 4 + WatchStopHandle, 5 + Ref, 6 + shallowRef, 7 + ref, 8 + watchEffect, 9 + reactive, 10 + isRef, 11 + } from 'vue'; 4 12 5 13 import { Subscription, Source, pipe, subscribe, onEnd } from 'wonka'; 6 14 ··· 14 22 RequestPolicy, 15 23 Operation, 16 24 createRequest, 17 - GraphQLRequest, 18 25 } from '@urql/core'; 19 26 20 27 import { useClient } from './useClient'; 21 - import { unwrapPossibleProxy } from './utils'; 28 + import { unwrapPossibleProxy, updateShallowRef } from './utils'; 22 29 23 30 type MaybeRef<T> = T | Ref<T>; 24 31 type MaybeRefObj<T extends {}> = { [K in keyof T]: MaybeRef<T[K]> }; ··· 258 265 ? _args.pause 259 266 : ref(!!_args.pause); 260 267 261 - const request: Ref<GraphQLRequest<T, V>> = ref( 262 - createRequest<T, V>( 268 + const input = shallowRef({ 269 + request: createRequest<T, V>( 263 270 unwrapPossibleProxy(args.query as any), 264 271 unwrapPossibleProxy<V>(args.variables as V) 265 - ) as any 266 - ); 272 + ), 273 + requestPolicy: unwrapPossibleProxy(args.requestPolicy), 274 + isPaused: isPaused.value, 275 + }); 267 276 268 277 const source: Ref<Source<OperationResult<T, V>> | undefined> = ref(); 269 278 270 279 stops.push( 271 280 watchEffect(() => { 272 - const newRequest = createRequest<T, V>( 273 - unwrapPossibleProxy(args.query as any), 274 - unwrapPossibleProxy<V>(args.variables as V) 275 - ); 276 - if (request.value.key !== newRequest.key) { 277 - request.value = newRequest; 278 - } 281 + updateShallowRef(input, { 282 + request: createRequest<T, V>( 283 + unwrapPossibleProxy(args.query as any), 284 + unwrapPossibleProxy<V>(args.variables as V) 285 + ), 286 + requestPolicy: unwrapPossibleProxy(args.requestPolicy), 287 + isPaused: isPaused.value, 288 + }); 279 289 }, watchOptions) 280 290 ); 281 291 282 292 stops.push( 283 293 watchEffect(() => { 284 - source.value = !isPaused.value 285 - ? client.value.executeQuery<T, V>(request.value, { 294 + source.value = !input.value.isPaused 295 + ? client.value.executeQuery<T, V>(input.value.request, { 286 296 requestPolicy: unwrapPossibleProxy( 287 297 args.requestPolicy 288 298 ) as RequestPolicy, ··· 301 311 fetching, 302 312 isPaused, 303 313 executeQuery(opts?: Partial<OperationContext>): UseQueryResponse<T, V> { 304 - const s = (source.value = client.value.executeQuery<T, V>(request.value, { 305 - requestPolicy: unwrapPossibleProxy(args.requestPolicy) as RequestPolicy, 306 - ...args.context, 307 - ...opts, 308 - })); 314 + const s = (source.value = client.value.executeQuery<T, V>( 315 + input.value.request, 316 + { 317 + requestPolicy: unwrapPossibleProxy( 318 + args.requestPolicy 319 + ) as RequestPolicy, 320 + ...args.context, 321 + ...opts, 322 + } 323 + )); 309 324 310 325 return { 311 326 ...response,
+30 -19
packages/vue-urql/src/useSubscription.ts
··· 2 2 3 3 import { Source, pipe, subscribe, onEnd } from 'wonka'; 4 4 5 - import { WatchStopHandle, Ref, ref, watchEffect, reactive, isRef } from 'vue'; 5 + import { 6 + WatchStopHandle, 7 + Ref, 8 + ref, 9 + shallowRef, 10 + watchEffect, 11 + reactive, 12 + isRef, 13 + } from 'vue'; 6 14 7 15 import { 8 16 Client, ··· 13 21 OperationContext, 14 22 Operation, 15 23 createRequest, 16 - GraphQLRequest, 17 24 } from '@urql/core'; 18 25 19 26 import { useClient } from './useClient'; 20 - import { unwrapPossibleProxy } from './utils'; 27 + import { unwrapPossibleProxy, updateShallowRef } from './utils'; 21 28 22 29 type MaybeRef<T> = Exclude<T, void> | Ref<Exclude<T, void>>; 23 30 type MaybeRefObj<T extends {}> = { [K in keyof T]: MaybeRef<T[K]> }; ··· 259 266 ? _args.pause 260 267 : ref(!!_args.pause); 261 268 262 - const request: Ref<GraphQLRequest<T, V>> = ref( 263 - createRequest<T, V>( 269 + const input = shallowRef({ 270 + request: createRequest<T, V>( 264 271 unwrapPossibleProxy(args.query as any), 265 272 unwrapPossibleProxy<V>(args.variables as V) 266 - ) as any 267 - ); 273 + ), 274 + isPaused: isPaused.value, 275 + }); 268 276 269 277 const source: Ref<Source<OperationResult<T, V>> | undefined> = ref(); 270 278 271 279 stops.push( 272 280 watchEffect(() => { 273 - const newRequest = createRequest<T, V>( 274 - unwrapPossibleProxy(args.query as any), 275 - unwrapPossibleProxy<V>(args.variables as V) 276 - ); 277 - if (request.value.key !== newRequest.key) { 278 - request.value = newRequest; 279 - } 281 + updateShallowRef(input, { 282 + request: createRequest<T, V>( 283 + unwrapPossibleProxy(args.query as any), 284 + unwrapPossibleProxy<V>(args.variables as V) 285 + ), 286 + isPaused: isPaused.value, 287 + }); 280 288 }, watchOptions) 281 289 ); 282 290 283 291 stops.push( 284 292 watchEffect(() => { 285 293 source.value = !isPaused.value 286 - ? client.value.executeSubscription<T, V>(request.value, { 294 + ? client.value.executeSubscription<T, V>(input.value.request, { 287 295 ...(unwrapPossibleProxy(args.context) as Partial<OperationContext>), 288 296 }) 289 297 : undefined; ··· 333 341 executeSubscription( 334 342 opts?: Partial<OperationContext> 335 343 ): UseSubscriptionResponse<T, R, V> { 336 - source.value = client.value.executeSubscription<T, V>(request.value, { 337 - ...unwrapPossibleProxy(args.context), 338 - ...opts, 339 - }); 344 + source.value = client.value.executeSubscription<T, V>( 345 + input.value.request, 346 + { 347 + ...unwrapPossibleProxy(args.context), 348 + ...opts, 349 + } 350 + ); 340 351 341 352 return state; 342 353 },
+32 -1
packages/vue-urql/src/utils.ts
··· 1 - import { Ref, isRef } from 'vue'; 1 + import { GraphQLRequest, AnyVariables } from '@urql/core'; 2 + import { Ref, ShallowRef, isRef } from 'vue'; 2 3 3 4 export function unwrapPossibleProxy<V>(possibleProxy: V | Ref<V>): V { 4 5 return possibleProxy && isRef(possibleProxy) 5 6 ? possibleProxy.value 6 7 : possibleProxy; 7 8 } 9 + 10 + export interface RequestState< 11 + Data = any, 12 + Variables extends AnyVariables = AnyVariables 13 + > { 14 + request: GraphQLRequest<Data, Variables>; 15 + isPaused: boolean; 16 + } 17 + 18 + export function createRequestState< 19 + Data = any, 20 + Variables extends AnyVariables = AnyVariables 21 + >( 22 + request: GraphQLRequest<Data, Variables>, 23 + isPaused: boolean 24 + ): RequestState<Data, Variables> { 25 + return { request, isPaused }; 26 + } 27 + 28 + export const updateShallowRef = <T extends Record<string, any>>( 29 + ref: ShallowRef<T>, 30 + next: T 31 + ) => { 32 + for (const key in next) { 33 + if (ref.value[key] !== next[key]) { 34 + ref.value = next; 35 + return; 36 + } 37 + } 38 + };