Skip to content

Commit

Permalink
chore: hide queryRef in a Symbol (closes #10875)
Browse files Browse the repository at this point in the history
  • Loading branch information
alessbell committed Jun 23, 2023
1 parent 659539e commit ccab651
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 26 deletions.
19 changes: 15 additions & 4 deletions src/react/cache/QueryReference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,31 @@ import { NetworkStatus, isNetworkRequestSettled } from '../../core';
import type { ObservableSubscription } from '../../utilities';
import { createFulfilledPromise, createRejectedPromise } from '../../utilities';
import type { CacheKey } from './types';
import type { useBackgroundQuery, useReadQuery } from '../hooks';

type Listener<TData> = (promise: Promise<ApolloQueryResult<TData>>) => void;

type FetchMoreOptions<TData> = Parameters<
ObservableQuery<TData>['fetchMore']
>[0];
>[0];

export const QUERY_REFERENCE_SYMBOL: unique symbol = Symbol();
/**
* A `QueryReference` is an opaque object returned by {@link useBackgroundQuery}.
* A child component reading the `QueryReference` via {@link useReadQuery} will
* suspend until the promise resolves.
*/
export interface QueryReference<TData = unknown> {
[QUERY_REFERENCE_SYMBOL]: InternalQueryReference<TData>;
}

interface QueryReferenceOptions {
interface InternalQueryReferenceOptions {
key: CacheKey;
onDispose?: () => void;
autoDisposeTimeoutMs?: number;
}

export class QueryReference<TData = unknown> {
export class InternalQueryReference<TData = unknown> {
public result: ApolloQueryResult<TData>;
public readonly key: CacheKey;
public readonly observable: ObservableQuery<TData>;
Expand All @@ -41,7 +52,7 @@ export class QueryReference<TData = unknown> {

constructor(
observable: ObservableQuery<TData>,
options: QueryReferenceOptions
options: InternalQueryReferenceOptions
) {
this.listen = this.listen.bind(this);
this.handleNext = this.handleNext.bind(this);
Expand Down
8 changes: 4 additions & 4 deletions src/react/cache/SuspenseCache.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Trie } from '@wry/trie';
import type { ObservableQuery } from '../../core';
import { canUseWeakMap } from '../../utilities';
import { QueryReference } from './QueryReference';
import { InternalQueryReference } from './QueryReference';
import type { CacheKey } from './types';

interface SuspenseCacheOptions {
Expand All @@ -19,7 +19,7 @@ interface SuspenseCacheOptions {
}

export class SuspenseCache {
private queryRefs = new Trie<{ current?: QueryReference }>(canUseWeakMap);
private queryRefs = new Trie<{ current?: InternalQueryReference }>(canUseWeakMap);
private options: SuspenseCacheOptions;

constructor(options: SuspenseCacheOptions = Object.create(null)) {
Expand All @@ -33,7 +33,7 @@ export class SuspenseCache {
const ref = this.queryRefs.lookupArray(cacheKey);

if (!ref.current) {
ref.current = new QueryReference(createObservable(), {
ref.current = new InternalQueryReference(createObservable(), {
key: cacheKey,
autoDisposeTimeoutMs: this.options.autoDisposeTimeoutMs,
onDispose: () => {
Expand All @@ -42,6 +42,6 @@ export class SuspenseCache {
});
}

return ref.current as QueryReference<TData>;
return ref.current as InternalQueryReference<TData>;
}
}
21 changes: 11 additions & 10 deletions src/react/hooks/__tests__/useBackgroundQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
import { concatPagination, offsetLimitPagination } from '../../../utilities';
import { useBackgroundQuery, useReadQuery } from '../useBackgroundQuery';
import { ApolloProvider } from '../../context';
import { QUERY_REFERENCE_SYMBOL } from '../../cache/QueryReference';
import { SuspenseCache } from '../../cache';
import { InMemoryCache } from '../../../cache';
import {
Expand Down Expand Up @@ -617,7 +618,7 @@ describe('useBackgroundQuery', () => {

const [queryRef] = result.current;

const _result = await queryRef.promise;
const _result = await queryRef[QUERY_REFERENCE_SYMBOL].promise;

expect(_result).toEqual({
data: { hello: 'world 1' },
Expand Down Expand Up @@ -654,7 +655,7 @@ describe('useBackgroundQuery', () => {

const [queryRef] = result.current;

const _result = await queryRef.promise;
const _result = await queryRef[QUERY_REFERENCE_SYMBOL].promise;

await waitFor(() => {
expect(_result).toEqual({
Expand Down Expand Up @@ -739,7 +740,7 @@ describe('useBackgroundQuery', () => {

const [queryRef] = result.current;

const _result = await queryRef.promise;
const _result = await queryRef[QUERY_REFERENCE_SYMBOL].promise;

await waitFor(() => {
expect(_result).toMatchObject({
Expand Down Expand Up @@ -803,7 +804,7 @@ describe('useBackgroundQuery', () => {

const [queryRef] = result.current;

const _result = await queryRef.promise;
const _result = await queryRef[QUERY_REFERENCE_SYMBOL].promise;
const resultSet = new Set(_result.data.results);
const values = Array.from(resultSet).map((item) => item.value);

Expand Down Expand Up @@ -868,7 +869,7 @@ describe('useBackgroundQuery', () => {

const [queryRef] = result.current;

const _result = await queryRef.promise;
const _result = await queryRef[QUERY_REFERENCE_SYMBOL].promise;
const resultSet = new Set(_result.data.results);
const values = Array.from(resultSet).map((item) => item.value);

Expand Down Expand Up @@ -913,7 +914,7 @@ describe('useBackgroundQuery', () => {

const [queryRef] = result.current;

const _result = await queryRef.promise;
const _result = await queryRef[QUERY_REFERENCE_SYMBOL].promise;

expect(_result).toEqual({
data: { hello: 'from link' },
Expand Down Expand Up @@ -956,7 +957,7 @@ describe('useBackgroundQuery', () => {

const [queryRef] = result.current;

const _result = await queryRef.promise;
const _result = await queryRef[QUERY_REFERENCE_SYMBOL].promise;

expect(_result).toEqual({
data: { hello: 'from cache' },
Expand Down Expand Up @@ -1006,7 +1007,7 @@ describe('useBackgroundQuery', () => {

const [queryRef] = result.current;

const _result = await queryRef.promise;
const _result = await queryRef[QUERY_REFERENCE_SYMBOL].promise;

expect(_result).toEqual({
data: { foo: 'bar', hello: 'from link' },
Expand Down Expand Up @@ -1049,7 +1050,7 @@ describe('useBackgroundQuery', () => {

const [queryRef] = result.current;

const _result = await queryRef.promise;
const _result = await queryRef[QUERY_REFERENCE_SYMBOL].promise;

expect(_result).toEqual({
data: { hello: 'from link' },
Expand Down Expand Up @@ -1095,7 +1096,7 @@ describe('useBackgroundQuery', () => {

const [queryRef] = result.current;

const _result = await queryRef.promise;
const _result = await queryRef[QUERY_REFERENCE_SYMBOL].promise;

expect(_result).toEqual({
data: { hello: 'from link' },
Expand Down
13 changes: 8 additions & 5 deletions src/react/hooks/useBackgroundQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import type {
} from '../../core';
import { NetworkStatus } from '../../core';
import { useApolloClient } from './useApolloClient';
import type { QueryReference } from '../cache/QueryReference';
import {
QUERY_REFERENCE_SYMBOL,
type QueryReference,
} from '../cache/QueryReference';
import type { SuspenseQueryHookOptions, NoInfer } from '../types/types';
import { __use } from './internal';
import { useSuspenseCache } from './useSuspenseCache';
Expand Down Expand Up @@ -188,7 +191,7 @@ export function useBackgroundQuery<

return useMemo(() => {
return [
queryRef,
{ [QUERY_REFERENCE_SYMBOL]: queryRef},
{
fetchMore,
refetch,
Expand All @@ -197,9 +200,9 @@ export function useBackgroundQuery<
}, [queryRef, fetchMore, refetch]);
}

export function useReadQuery<TData>(queryRef: QueryReference<TData>) {
export function useReadQuery<TData>(_queryRef: QueryReference<TData>) {
const [, forceUpdate] = useState(0);

const queryRef = _queryRef[QUERY_REFERENCE_SYMBOL];
invariant(
queryRef.promiseCache,
'It appears that `useReadQuery` was used outside of `useBackgroundQuery`. ' +
Expand Down Expand Up @@ -233,7 +236,7 @@ export function useReadQuery<TData>(queryRef: QueryReference<TData>) {
}, [queryRef]);

const result =
queryRef.watchQueryOptions.fetchPolicy === 'standby'
queryRef.watchQueryOptions.fetchPolicy === 'standby'
? skipResult
: __use(promise);

Expand Down
6 changes: 3 additions & 3 deletions src/react/hooks/useSuspenseQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import type {
} from '../types/types';
import { useDeepMemo, useStrictModeSafeCleanupEffect, __use } from './internal';
import { useSuspenseCache } from './useSuspenseCache';
import type { QueryReference } from '../cache/QueryReference';
import type { InternalQueryReference } from '../cache/QueryReference';
import { canonicalStringify } from '../../cache';

export interface UseSuspenseQueryResult<
Expand Down Expand Up @@ -296,8 +296,8 @@ export function toApolloError(result: ApolloQueryResult<any>) {
: result.error;
}

export function useTrackedQueryRefs(queryRef: QueryReference) {
const trackedQueryRefs = useRef(new Set<QueryReference>());
export function useTrackedQueryRefs(queryRef: InternalQueryReference) {
const trackedQueryRefs = useRef(new Set<InternalQueryReference>());

trackedQueryRefs.current.add(queryRef);

Expand Down

0 comments on commit ccab651

Please sign in to comment.