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

Add support for passing in client into useFragment #11525

Merged
merged 14 commits into from
Feb 1, 2024
5 changes: 5 additions & 0 deletions .changeset/brave-cougars-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/client": patch
---

Allows passing in client via options to useFragment
44 changes: 44 additions & 0 deletions src/react/hooks/__tests__/useFragment.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,50 @@ describe("useFragment", () => {
screen.getByText(/Item #1/);
});

it("allows the client to be overriden", () => {
const ItemFragment: TypedDocumentNode<Item> = gql`
fragment ItemFragment on Item {
id
text
}
`;
const cache = new InMemoryCache();
const item = { __typename: "Item", id: 1, text: "Item #1" };
cache.writeFragment({
fragment: ItemFragment,
data: item,
});
const client = new ApolloClient({
cache,
});
function Component() {
const { data } = useFragment({
fragment: ItemFragment,
from: { __typename: "Item", id: 1 },
client,
});
return <>{data.text}</>;
}

// Not providing MockProvider (client must be specified)
render(<Component />);

// would throw if client is not provided
screen.getByText(/Item #1/);
vezaynk marked this conversation as resolved.
Show resolved Hide resolved
});

it("throws if no client is provided", () => {
function Component() {
const { data } = useFragment({
fragment: ItemFragment,
from: { __typename: "Item", id: 1 },
});
return <>{data.text}</>;
}

expect(() => render(<Component />)).toThrow(/pass an ApolloClient/);
vezaynk marked this conversation as resolved.
Show resolved Hide resolved
});

it.each<TypedDocumentNode<{ list: Item[] }>>([
// This query uses a basic field-level @nonreactive directive.
gql`
Expand Down
13 changes: 11 additions & 2 deletions src/react/hooks/useFragment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {

import { useApolloClient } from "./useApolloClient.js";
import { useSyncExternalStore } from "./useSyncExternalStore.js";
import type { OperationVariables } from "../../core/index.js";
import type { ApolloClient, OperationVariables } from "../../core/index.js";
import type { NoInfer } from "../types/types.js";
import { useDeepMemo, useLazyRef } from "./internal/index.js";

Expand All @@ -28,6 +28,15 @@ export interface UseFragmentOptions<TData, TVars>
from: StoreObject | Reference | string;
// Override this field to make it optional (default: true).
optimistic?: boolean;
/**
* The instance of {@link ApolloClient} to use to lookup the fragment.
vezaynk marked this conversation as resolved.
Show resolved Hide resolved
*
* By default, the instance that's passed down via context is used, but you
* can provide a different instance here.
*
* @docGroup 1. Operation options
*/
client?: ApolloClient<any>;
alessbell marked this conversation as resolved.
Show resolved Hide resolved
}

export type UseFragmentResult<TData> =
Expand All @@ -45,7 +54,7 @@ export type UseFragmentResult<TData> =
export function useFragment<TData = any, TVars = OperationVariables>(
options: UseFragmentOptions<TData, TVars>
): UseFragmentResult<TData> {
const { cache } = useApolloClient();
const { cache } = useApolloClient(options.client);

const diffOptions = useDeepMemo<Cache.DiffOptions<TData, TVars>>(() => {
const {
Expand Down
Loading