diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4a8ee3747fe..ee38144ef7c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## Apollo Client 3.4.12 (not yet released)
+
+### Bug Fixes
+
+- Improve handling of falsy `existing` and/or `incoming` parameters in `relayStylePagination` field policy helper function.
+ [@bubba](https://github.com/bubba) and [@benjamn](https://github.com/benjamn) in [#8733](https://github.com/apollographql/apollo-client/pull/8733)
+
## Apollo Client 3.4.11
### Bug Fixes
diff --git a/src/utilities/policies/__tests__/relayStylePagination.test.ts b/src/utilities/policies/__tests__/relayStylePagination.test.ts
index 89583da4ef9..a2e19321bd4 100644
--- a/src/utilities/policies/__tests__/relayStylePagination.test.ts
+++ b/src/utilities/policies/__tests__/relayStylePagination.test.ts
@@ -203,6 +203,66 @@ describe('relayStylePagination', () => {
});
});
+ it('should preserve existing if incoming is null', () => {
+ const existingEdges = [
+ { cursor: 'alpha', node: makeReference("fakeAlpha") },
+ ];
+
+ const fakeExisting = {
+ edges: existingEdges,
+ pageInfo: {
+ hasPreviousPage: false,
+ hasNextPage: true,
+ startCursor: 'alpha',
+ endCursor: 'alpha'
+ },
+ };
+
+ const fakeIncoming = null;
+
+ const fakeOptions = {
+ ...options,
+ args: {
+ after: 'alpha',
+ },
+ };
+
+ const result = merge(
+ fakeExisting,
+ fakeIncoming,
+ fakeOptions,
+ );
+
+ expect(result).toEqual(fakeExisting);
+ })
+
+ it('should replace existing null with incoming', () => {
+ const incomingEdges = [
+ { cursor: 'alpha', node: makeReference("fakeAlpha") },
+ ];
+ const incoming = {
+ edges: incomingEdges,
+ pageInfo: {
+ hasPreviousPage: false,
+ hasNextPage: true,
+ startCursor: 'alpha',
+ endCursor: 'alpha'
+ },
+ };
+ const result = merge(
+ null,
+ incoming,
+ {
+ ...options,
+ args: {
+ after: 'alpha',
+ },
+ },
+ );
+
+ expect(result).toEqual(incoming);
+ })
+
it('should maintain extra PageInfo properties', () => {
const existingEdges = [
{ cursor: 'alpha', node: makeReference("fakeAlpha") },
diff --git a/src/utilities/policies/pagination.ts b/src/utilities/policies/pagination.ts
index e6471b2d99d..27a9b97bea4 100644
--- a/src/utilities/policies/pagination.ts
+++ b/src/utilities/policies/pagination.ts
@@ -80,9 +80,9 @@ export type TIncomingRelay = {
};
export type RelayFieldPolicy = FieldPolicy<
- TExistingRelay,
- TIncomingRelay,
- TIncomingRelay
+ TExistingRelay | null,
+ TIncomingRelay | null,
+ TIncomingRelay | null
>;
// As proof of the flexibility of field policies, this function generates
@@ -95,7 +95,7 @@ export function relayStylePagination(
keyArgs,
read(existing, { canRead, readField }) {
- if (!existing) return;
+ if (!existing) return existing;
const edges: TRelayEdge[] = [];
let firstEdgeCursor = "";
@@ -133,7 +133,15 @@ export function relayStylePagination(
};
},
- merge(existing = makeEmptyData(), incoming, { args, isReference, readField }) {
+ merge(existing, incoming, { args, isReference, readField }) {
+ if (!existing) {
+ existing = makeEmptyData();
+ }
+
+ if (!incoming) {
+ return existing;
+ }
+
const incomingEdges = incoming.edges ? incoming.edges.map(edge => {
if (isReference(edge = { ...edge })) {
// In case edge is a Reference, we read out its cursor field and