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.

Add react-wonka (#499)

* add react-wonka

* upgrade wonka

* remove scheduler peerdep

* add lockfile

authored by

Jovi De Croock and committed by
Phil Plückthun
e7227c29 625c2aac

+15 -155
+3 -3
package.json
··· 134 134 }, 135 135 "peerDependencies": { 136 136 "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0", 137 - "react": ">= 16.8.0", 138 - "scheduler": ">= 0.16.0" 137 + "react": ">= 16.8.0" 139 138 }, 140 139 "dependencies": { 141 - "wonka": "^4.0.2" 140 + "react-wonka": "^2.0.0", 141 + "wonka": "^4.0.3" 142 142 } 143 143 }
-146
src/hooks/useOperator.ts
··· 1 - /* eslint-disable @typescript-eslint/no-use-before-define */ 2 - /* eslint-disable react-hooks/exhaustive-deps */ 3 - 4 - import { 5 - useReducer, 6 - useRef, 7 - useEffect, 8 - useLayoutEffect, 9 - Dispatch, 10 - } from 'react'; 11 - 12 - import { Subject, Operator, makeSubject, subscribe, pipe } from 'wonka'; 13 - 14 - import { 15 - CallbackNode, 16 - unstable_scheduleCallback as scheduleCallback, 17 - unstable_cancelCallback as cancelCallback, 18 - unstable_getCurrentPriorityLevel as getPriorityLevel, 19 - } from 'scheduler'; 20 - 21 - type TeardownFn = () => void; 22 - 23 - interface State<R, T = R> { 24 - subject: Subject<T>; 25 - onValue: Dispatch<R>; 26 - teardown: null | TeardownFn; 27 - task: null | CallbackNode; 28 - value: R; 29 - } 30 - 31 - const isServerSide = typeof window === 'undefined'; 32 - const useIsomorphicEffect = !isServerSide ? useLayoutEffect : useEffect; 33 - 34 - /** 35 - * Creates a stream of `input` as it's changing and pipes this stream 36 - * into the operator which creates what becomes the output of this hook. 37 - * 38 - * This hooks supports creating a synchronous, stateful value that is 39 - * updated immediately on mount and is then updated using normal effects. 40 - * It has been built to be safe for normal-mode, concurrent-mode, 41 - * strict-mode and suspense. 42 - */ 43 - export const useOperator = <T, R>( 44 - operator: Operator<T, R>, 45 - input: T, 46 - init?: R 47 - ): [R, Dispatch<T>] => { 48 - const subscription = useRef<State<R, T>>({ 49 - subject: makeSubject<T>(), 50 - value: init as R, 51 - onValue: (value: R) => { 52 - // Before the effect triggers we update the initial value synchronously 53 - subscription.current.value = value; 54 - }, 55 - teardown: null, 56 - task: null, 57 - }); 58 - 59 - // This is called from effects to update the current output value 60 - const [, setValue] = useReducer((x: number, value: R) => { 61 - subscription.current.value = value; 62 - return x + 1; 63 - }, 0); 64 - 65 - // On mount, subscribe to the operator using the subject and schedule a teardown using scheduler (1) 66 - if (subscription.current.teardown === null) { 67 - observe( 68 - operator, 69 - subscription.current, 70 - /* shouldScheduleTeardown */ !isServerSide 71 - ); 72 - // Send the initial input value to the operator; this may call `onValue` synchronously 73 - subscription.current.subject.next(input); 74 - if (isServerSide && subscription.current.teardown !== null) { 75 - (subscription.current.teardown as any)(); 76 - } 77 - } 78 - 79 - // We utilise useLayoutEffect to cancel the scheduled teardown again 80 - // This works because A) useLayoutEffect runs synchronously after mount 81 - // during the commit phase, and B) if it runs we know that useEffect 82 - // is also going to run. 83 - useIsomorphicEffect(() => { 84 - // Cancel the scheduled teardown 85 - if (subscription.current.task !== null) { 86 - cancelCallback(subscription.current.task); 87 - } 88 - 89 - // On unmount we call the teardown manually to stop the subscription 90 - return () => { 91 - if (subscription.current.teardown !== null) { 92 - subscription.current.teardown(); 93 - } 94 - }; 95 - }, []); 96 - 97 - useEffect(() => { 98 - const isInitial = subscription.current.onValue !== setValue; 99 - // Once the effect runs, we update onValue to update this component properly 100 - // instead of mutating 101 - subscription.current.onValue = setValue; 102 - 103 - // If the subscription got cancelled, which may happen during long suspense phases (?), 104 - // we restart it here without scheduling a teardown 105 - if (subscription.current.teardown === null) { 106 - observe( 107 - operator, 108 - subscription.current, 109 - /* shouldScheduleTeardown */ false 110 - ); 111 - } 112 - 113 - // If the input value has changed (except during the initial mount) we send it to the operator 114 - // This may call `setValue` which schedules an update 115 - if (!isInitial) { 116 - subscription.current.subject.next(input); 117 - } 118 - }, [input]); 119 - 120 - return [subscription.current.value, subscription.current.subject.next]; 121 - }; 122 - 123 - const observe = <R, T>( 124 - operator: Operator<T, R>, 125 - subscription: State<R, T>, 126 - shouldScheduleTeardown: boolean 127 - ) => { 128 - // Start the subscription using the subject and operator 129 - const { unsubscribe } = pipe( 130 - operator(subscription.subject.source), 131 - subscribe((value: R) => subscription.onValue(value)) 132 - ); 133 - 134 - // Update the current teardown to now be the subscription's unsubcribe function 135 - subscription.teardown = unsubscribe as TeardownFn; 136 - 137 - // See (1): We schedule a teardown on mount that is cancelled by useLayoutEffect, 138 - // unless we're not expecting effects to run at all and the component not to be 139 - // rendered, which means this callback won't be cancelled and will unsubscribe. 140 - if (shouldScheduleTeardown) { 141 - subscription.task = scheduleCallback( 142 - getPriorityLevel(), 143 - subscription.teardown 144 - ); 145 - } 146 - };
+1 -1
src/hooks/useQuery.ts
··· 1 1 import { DocumentNode } from 'graphql'; 2 2 import { useCallback, useMemo } from 'react'; 3 3 import { pipe, concat, fromValue, switchMap, map, scan } from 'wonka'; 4 + import { useOperator } from 'react-wonka'; 4 5 5 6 import { useClient } from '../context'; 6 7 import { OperationContext, RequestPolicy } from '../types'; 7 8 import { CombinedError } from '../utils'; 8 9 import { useRequest } from './useRequest'; 9 - import { useOperator } from './useOperator'; 10 10 import { initialState } from './constants'; 11 11 12 12 export interface UseQueryArgs<V> {
+1 -1
src/hooks/useSubscription.ts
··· 1 1 import { DocumentNode } from 'graphql'; 2 2 import { useCallback, useRef, useMemo } from 'react'; 3 3 import { pipe, concat, fromValue, switchMap, map, scan } from 'wonka'; 4 + import { useOperator } from 'react-wonka'; 4 5 5 6 import { useClient } from '../context'; 6 7 import { CombinedError } from '../utils'; 7 8 import { OperationContext } from '../types'; 8 9 import { useRequest } from './useRequest'; 9 - import { useOperator } from './useOperator'; 10 10 import { initialState } from './constants'; 11 11 12 12 export interface UseSubscriptionArgs<V> {
+1
tsconfig.json
··· 1 1 { 2 2 "compilerOptions": { 3 3 "esModuleInterop": true, 4 + "forceConsistentCasingInFileNames": true, 4 5 "noUnusedLocals": true, 5 6 "rootDir": "./src", 6 7 "baseUrl": ".",
+9 -4
yarn.lock
··· 4666 4666 react-is "^16.8.6" 4667 4667 scheduler "^0.17.0" 4668 4668 4669 + react-wonka@^2.0.0: 4670 + version "2.0.0" 4671 + resolved "https://registry.yarnpkg.com/react-wonka/-/react-wonka-2.0.0.tgz#d62d87c9c93ec3e603ecf1582df3615aadc5c2e9" 4672 + integrity sha512-7q0CNBnSltRyzb61joCxKqVntHbRJRhP/WPxEx+zM8l9Yd+0IRevJuPG8iCamgrGphusX5xtEtd4yyX7qvRM1g== 4673 + 4669 4674 react@^16.11.0: 4670 4675 version "16.11.0" 4671 4676 resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb" ··· 5930 5935 dependencies: 5931 5936 string-width "^1.0.2 || 2" 5932 5937 5933 - wonka@^4.0.2: 5934 - version "4.0.2" 5935 - resolved "https://registry.yarnpkg.com/wonka/-/wonka-4.0.2.tgz#32004bab7373da2150711fc703f7f12404dfdcb7" 5936 - integrity sha512-3Iwtr5agZFMs9j3c1fLn44FKi62G4XlNMbTluMbsF4fmJE6DDgVvkq7HwVOExWXOyGEfs8awOTTOebWbqG4quw== 5938 + wonka@^4.0.3: 5939 + version "4.0.3" 5940 + resolved "https://registry.yarnpkg.com/wonka/-/wonka-4.0.3.tgz#95babdc479714232c11dcd99093ab2fee47842d8" 5941 + integrity sha512-lwSDBv375yZYC+P4sQxhZfF9izvtsdBZxRt4r5eHLmJdCFjQu500zqSO73rxXpRuoPgJtS3/BCiwOxHcBeftjg== 5937 5942 5938 5943 wordwrap@~0.0.2: 5939 5944 version "0.0.3"