Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deprecate useFragement returnPartialData option #10764

Merged
merged 3 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/brave-buttons-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/client": patch
---

deprecate `useFragement` `returnPartialData` option
phryneas marked this conversation as resolved.
Show resolved Hide resolved
90 changes: 90 additions & 0 deletions src/react/hooks/__tests__/useFragment.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -911,4 +911,94 @@ describe("useFragment", () => {
]);
});
});

describe("tests with incomplete data", () => {
let cache: InMemoryCache, wrapper: React.FunctionComponent;
const ItemFragment = gql`
fragment ItemFragment on Item {
id
text
}
`;

beforeEach(() => {
cache = new InMemoryCache();

wrapper = ({ children }: any) => <MockedProvider cache={cache}>{children}</MockedProvider>;

// silence the console for the incomplete fragment write
const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
cache.writeFragment({
fragment: ItemFragment,
data: {
__typename: "Item",
id: 5,
},
});
spy.mockRestore();
});

it("assumes `returnPartialData: true` per default", () => {
const { result } = renderHook(
() =>
useFragment({
fragment: ItemFragment,
from: { __typename: "Item", id: 5 },
}),
{ wrapper }
);

expect(result.current.data).toEqual({ __typename: "Item", id: 5 });
expect(result.current.complete).toBe(false);
});

it("throws an exception with `returnPartialData: false` if only partial data is available", () => {
// this is actually not intended behavuor, but it is the current behaviour
phryneas marked this conversation as resolved.
Show resolved Hide resolved
// let's document it in a test until we remove `returnPartialData` in 3.8

let error: Error;

renderHook(
() => {
// we can't just `expect(() => renderHook(...)).toThrow(...)` because it will render a second time, resulting in an uncaught exception
try {
useFragment({
fragment: ItemFragment,
from: { __typename: "Item", id: 5 },
returnPartialData: false,
});
} catch (e) {
error = e;
}
},
{ wrapper }
);

expect(error!.toString()).toMatch(`Error: Can't find field 'text' on Item:5 object`);
});

it("throws an exception with `returnPartialData: false` if no data is available", () => {
// this is actually not intended behavuor, but it is the current behaviour
phryneas marked this conversation as resolved.
Show resolved Hide resolved
// let's document it in a test until we remove `returnPartialData` in 3.8
let error: Error;

renderHook(
() => {
// we can't just `expect(() => renderHook(...)).toThrow(...)` because it will render a second time, resulting in an uncaught exception
try {
useFragment({
fragment: ItemFragment,
from: { __typename: "Item", id: 6 },
returnPartialData: false,
});
} catch (e) {
error = e;
}
},
{ wrapper }
);

expect(error!.toString()).toMatch(`Error: Dangling reference to missing Item:6 object`);
});
});
});
15 changes: 12 additions & 3 deletions src/react/hooks/useFragment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,27 @@ import { OperationVariables } from "../../core";

export interface UseFragmentOptions<TData, TVars>
extends Omit<
Cache.DiffOptions<TData, TVars>,
Cache.DiffOptions<TData, TVars>,
phryneas marked this conversation as resolved.
Show resolved Hide resolved
| "id"
| "query"
| "optimistic"
| "previousResult"
>, Omit<
Cache.ReadFragmentOptions<TData, TVars>,
| "returnPartialData"
>, Omit<Cache.ReadFragmentOptions<TData, TVars>,
| "id"
| "returnPartialData"
> {
from: StoreObject | Reference | string;
// Override this field to make it optional (default: true).
optimistic?: boolean;

/**
* Whether to return incomplete data rather than null.
* Defaults to `true`.
* @deprecated This option will be removed in Apollo Client 3.8.
* Please check `result.missing` instead.
*/
returnPartialData?: boolean;
}

// Since the above definition of UseFragmentOptions can be hard to parse without
Expand Down