Skip to content

Commit

Permalink
Add support for passing in client into useFragment (#11525)
Browse files Browse the repository at this point in the history
Co-authored-by: Jerel Miller <jerelmiller@gmail.com>
Co-authored-by: Alessia Bellisario <github@bellisar.io>
  • Loading branch information
3 people committed Feb 1, 2024
1 parent e1794c4 commit dce923a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-cougars-applaud.md
@@ -0,0 +1,5 @@
---
"@apollo/client": patch
---

Allows passing in client via options to useFragment
50 changes: 50 additions & 0 deletions src/react/hooks/__tests__/useFragment.test.tsx
Expand Up @@ -333,6 +333,55 @@ 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}</>;
}

// Without a MockedProvider supplying the client via context,
// the client must be passed directly to the hook or an error is thrown
expect(() => render(<Component />)).not.toThrow(/pass an ApolloClient/);

// Item #1 is rendered
screen.getByText(/Item #1/);
});

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

// silence the console error
{
using _spy = spyOnConsole("error");
expect(() => render(<Component />)).toThrow(/pass an ApolloClient/);
}
});

it.each<TypedDocumentNode<{ list: Item[] }>>([
// This query uses a basic field-level @nonreactive directive.
gql`
Expand Down Expand Up @@ -1721,6 +1770,7 @@ describe.skip("Type Tests", () => {
optimistic?: boolean;
variables?: TVars;
canonizeResults?: boolean;
client?: ApolloClient<any>;
}>();
});
});
13 changes: 11 additions & 2 deletions src/react/hooks/useFragment.ts
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 look up the fragment.
*
* 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>;
}

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

0 comments on commit dce923a

Please sign in to comment.