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.

(react) - move subscription handler to a ref to avoid infinite loops (#1384)

* move subscription handler to a ref to avoid infinite loops

* simplify implementation

* fix typing issue

* add changeset

authored by

Jovi De Croock and committed by
GitHub
aa3f8ca9 d7214161

+22 -12
+5
.changeset/eleven-poems-juggle.md
··· 1 + --- 2 + 'urql': patch 3 + --- 4 + 5 + Fix issue where `useSubscription` would endlessly loop when the callback wasn't memoized
+17 -12
packages/react-urql/src/hooks/useSubscription.ts
··· 2 2 3 3 import { DocumentNode } from 'graphql'; 4 4 import { pipe, subscribe, onEnd } from 'wonka'; 5 - import { useEffect, useState, useCallback, useMemo } from 'react'; 5 + import { useEffect, useState, useCallback, useMemo, useRef } from 'react'; 6 6 7 7 import { 8 8 TypedDocumentNode, ··· 45 45 const client = useClient(); 46 46 const request = useRequest<Data, Variables>(args.query, args.variables); 47 47 48 + const handlerRef = useRef<SubscriptionHandler<Data, Result> | undefined>( 49 + handler 50 + ); 51 + handlerRef.current = handler; 52 + 48 53 const source = useMemo( 49 54 () => 50 55 !args.pause ? client.executeSubscription(request, args.context) : null, ··· 54 59 const deps = [client, request, args.context, args.pause] as const; 55 60 56 61 const [state, setState] = useState( 57 - () => 58 - [source, { ...initialState, fetching: !!source }, handler, deps] as const 62 + () => [source, { ...initialState, fetching: !!source }, deps] as const 59 63 ); 60 64 61 65 let currentResult = state[1]; 62 - if ( 63 - (source !== state[0] && hasDepsChanged(state[3], deps)) || 64 - handler !== state[2] 65 - ) { 66 + if (source !== state[0] && hasDepsChanged(state[2], deps)) { 66 67 setState([ 67 68 source, 68 69 (currentResult = computeNextState(state[1], { fetching: !!source })), 69 - handler, 70 70 deps, 71 71 ]); 72 72 } ··· 78 78 setState(state => { 79 79 const nextResult = computeNextState(state[1], result); 80 80 if (state[1] === nextResult) return state; 81 - if (state[2] && state[1].data !== nextResult.data) 82 - nextResult.data = state[2](state[1].data, nextResult.data!) as any; 83 - return [state[0], state[1], nextResult as any, state[3]]; 81 + if (handlerRef.current && state[1].data !== nextResult.data) { 82 + nextResult.data = handlerRef.current( 83 + state[1].data, 84 + nextResult.data! 85 + ) as any; 86 + } 87 + 88 + return [state[0], nextResult as any, state[2]]; 84 89 }); 85 90 }; 86 91 ··· 105 110 ...opts, 106 111 }); 107 112 108 - setState(state => [source, state[1], state[2], state[3]]); 113 + setState(state => [source, state[1], state[2]]); 109 114 }, 110 115 [client, args.context, request] 111 116 );