This repository has been archived by the owner on Apr 13, 2023. It is now read-only.
/
useBaseQuery.ts
66 lines (55 loc) · 1.88 KB
/
useBaseQuery.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { useContext, useEffect, useReducer, useRef } from 'react';
import {
getApolloContext,
OperationVariables,
QueryResult
} from '@apollo/react-common';
import { DocumentNode } from 'graphql';
import { QueryHookOptions, QueryOptions, QueryTuple } from '../types';
import { QueryData } from '../data/QueryData';
import { useDeepMemo } from './useDeepMemo';
export function useBaseQuery<TData = any, TVariables = OperationVariables>(
query: DocumentNode,
options?: QueryHookOptions<TData, TVariables>,
lazy = false
) {
const context = useContext(getApolloContext());
const [tick, forceUpdate] = useReducer(x => x + 1, 0);
const updatedOptions = options ? { ...options, query } : { query };
const queryDataRef = useRef<QueryData<TData, TVariables>>();
if (!queryDataRef.current) {
queryDataRef.current = new QueryData<TData, TVariables>({
options: updatedOptions as QueryOptions<TData, TVariables>,
context,
forceUpdate
});
}
const queryData = queryDataRef.current;
queryData.setOptions(updatedOptions);
queryData.context = context;
// `onError` and `onCompleted` callback functions will not always have a
// stable identity, so we'll exclude them from the memoization key to
// prevent `afterExecute` from being triggered un-necessarily.
const memo = {
options: { ...updatedOptions, onError: undefined, onCompleted: undefined },
context,
tick
};
const result = useDeepMemo(
() => (lazy ? queryData.executeLazy() : queryData.execute()),
memo
);
const queryResult = lazy
? (result as QueryTuple<TData, TVariables>)[1]
: (result as QueryResult<TData, TVariables>);
useEffect(() => queryData.afterExecute({ lazy }), [
queryResult.loading,
queryResult.networkStatus,
queryResult.error,
queryResult.data
]);
useEffect(() => {
return () => queryData.cleanup();
}, []);
return result;
}