Skip to content

Commit

Permalink
Introduce ObservableQuery#refresh as an alternative to refetch.
Browse files Browse the repository at this point in the history
The difference is that refresh overwrites existing fields by not passing
existing data to field merge functions, whereas refetch passes existing
data to merge functions, thereby combining it with the refetch result.

If we continue down this path, we can say "the solution to #7491 is to
switch from using refetch to using refresh," but that involves conscious
effort by the developer, and would mean maintaining two very similar
methods of the ObservableQuery class (refetch and refresh).
  • Loading branch information
benjamn committed Mar 9, 2021
1 parent 093c6c9 commit 4e3b7eb
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 7 deletions.
18 changes: 16 additions & 2 deletions src/core/ObservableQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,16 @@ export class ObservableQuery<
* the previous values of those variables will be used.
*/
public refetch(variables?: Partial<TVariables>): Promise<ApolloQueryResult<TData>> {
return this.refresh(variables, NetworkStatus.refetch);
}

// Forces a network query, like fetchMore and refetch, but overwrites
// existing cache fields with incoming data, rather than merging field
// values. Can be useful for restarting paginated fields with fresh data.
public refresh(
variables?: Partial<TVariables>,
networkStatus = NetworkStatus.refresh,
): Promise<ApolloQueryResult<TData>> {
const reobserveOptions: Partial<WatchQueryOptions<TVariables, TData>> = {
// Always disable polling for refetches.
pollInterval: 0,
Expand All @@ -250,9 +260,13 @@ export class ObservableQuery<

this.queryInfo.resetLastWrite();

return this.newReobserver(false).reobserve(
return (
networkStatus === NetworkStatus.refresh
? this.getReobserver()
: this.newReobserver(false)
).reobserve(
reobserveOptions,
NetworkStatus.refetch,
networkStatus,
);
}

Expand Down
6 changes: 3 additions & 3 deletions src/core/QueryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,7 @@ export class QueryManager<TStore> {
options: WatchQueryOptions<TVars, TData>,
// The initial networkStatus for this fetch, most often
// NetworkStatus.loading, but also possibly fetchMore, poll, refetch,
// or setVariables.
// refresh, or setVariables.
networkStatus = NetworkStatus.loading,
): Concast<ApolloQueryResult<TData>> {
const query = this.transform(options.query).document;
Expand Down Expand Up @@ -1039,7 +1039,7 @@ export class QueryManager<TStore> {
options: WatchQueryOptions<TVars, TData>,
// The initial networkStatus for this fetch, most often
// NetworkStatus.loading, but also possibly fetchMore, poll, refetch,
// or setVariables.
// refresh, or setVariables.
networkStatus: NetworkStatus,
): ConcastSourcesIterable<ApolloQueryResult<TData>> {
const {
Expand Down Expand Up @@ -1097,7 +1097,7 @@ export class QueryManager<TStore> {

const cacheWriteBehavior =
fetchPolicy === "no-cache" ? CacheWriteBehavior.FORBID :
networkStatus === NetworkStatus.refetch ? CacheWriteBehavior.OVERWRITE :
networkStatus === NetworkStatus.refresh ? CacheWriteBehavior.OVERWRITE :
CacheWriteBehavior.MERGE;

const resultsFromLink = () =>
Expand Down
15 changes: 14 additions & 1 deletion src/core/networkStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ export enum NetworkStatus {
*/
refetch = 4,

/**
* Similar to NetworkStatus.refetch, but existing cache fields will be
* overwritten by the incoming network data, rather than merging. Useful
* for restarting a paginated field with fresh initial data.
*
* This enum value uses the string "refetch" rather than a number,
* because it was added after the other values, and we did not want to
* change the existing numbers. Any other values added in the future
* should also use strings rather than numbers.
*/
refresh = "refresh",

/**
* Indicates that a polling query is currently in flight. So for example if you are polling a
* query every 10 seconds then the network status will switch to `poll` every 10 seconds whenever
Expand All @@ -52,5 +64,6 @@ export enum NetworkStatus {
export function isNetworkRequestInFlight(
networkStatus?: NetworkStatus,
): boolean {
return networkStatus ? networkStatus < 7 : false;
return networkStatus === "refresh" ||
(typeof networkStatus === "number" && networkStatus < 7);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Object {
"networkStatus": 1,
"previousData": undefined,
"refetch": [Function],
"refresh": [Function],
"startPolling": [Function],
"stopPolling": [Function],
"subscribeToMore": [Function],
Expand Down
4 changes: 4 additions & 0 deletions src/react/data/QueryData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,9 @@ export class QueryData<TData, TVariables> extends OperationData<
private obsRefetch = (variables?: Partial<TVariables>) =>
this.currentObservable?.refetch(variables);

private obsRefresh = (variables?: Partial<TVariables>) =>
this.currentObservable?.refresh(variables);

private obsFetchMore = (
fetchMoreOptions: FetchMoreQueryOptions<TVariables, TData> &
FetchMoreOptions<TData, TVariables>
Expand Down Expand Up @@ -530,6 +533,7 @@ export class QueryData<TData, TVariables> extends OperationData<
return {
variables: this.currentObservable?.variables,
refetch: this.obsRefetch,
refresh: this.obsRefresh,
fetchMore: this.obsFetchMore,
updateQuery: this.obsUpdateQuery,
startPolling: this.obsStartPolling,
Expand Down
3 changes: 2 additions & 1 deletion src/react/hoc/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApolloClient } from '../../core';
import { ApolloClient, ObservableQuery } from '../../core';
import { ApolloError } from '../../errors';
import {
ApolloQueryResult,
Expand Down Expand Up @@ -28,6 +28,7 @@ export interface QueryControls<
FetchMoreOptions<TData, TGraphQLVariables>
) => Promise<ApolloQueryResult<TData>>;
refetch: (variables?: TGraphQLVariables) => Promise<ApolloQueryResult<TData>>;
refresh: ObservableQuery<TData, TGraphQLVariables>["refresh"];
startPolling: (pollInterval: number) => void;
stopPolling: () => void;
subscribeToMore: (options: SubscribeToMoreOptions) => () => void;
Expand Down
1 change: 1 addition & 0 deletions src/react/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export type ObservableQueryFields<TData, TVariables> = Pick<
| 'subscribeToMore'
| 'updateQuery'
| 'refetch'
| 'refresh'
| 'variables'
> & {
fetchMore: ((
Expand Down

0 comments on commit 4e3b7eb

Please sign in to comment.