From 87977f7fa86423040b8fa7428a8138006ff3ed1e Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 09:57:27 -0700 Subject: [PATCH 01/34] Add additional sentence in fragment doc --- docs/source/data/fragments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.md b/docs/source/data/fragments.md index c3fff7a39c0..13aa1d64056 100644 --- a/docs/source/data/fragments.md +++ b/docs/source/data/fragments.md @@ -3,7 +3,7 @@ title: Fragments description: Share fields between operations --- -A [GraphQL fragment](http://graphql.org/learn/queries/#fragments) is a piece of logic that can be shared between multiple queries and mutations. +A [GraphQL fragment](http://graphql.org/learn/queries/#fragments) is a piece of logic that can be shared between multiple queries and mutations. Fragments are especially useful when used as [colocated fragments](#colocating-fragments) with components to define their data requirements. Here's the declaration of a `NameParts` fragment that can be used with any `Person` object: From faf70ac8d04e9e2145daba9b9e462f0661b1610f Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 10:19:31 -0700 Subject: [PATCH 02/34] Update example to use fragments in terms of components --- docs/source/data/fragments.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/source/data/fragments.md b/docs/source/data/fragments.md index 13aa1d64056..af58bbf557b 100644 --- a/docs/source/data/fragments.md +++ b/docs/source/data/fragments.md @@ -45,15 +45,15 @@ If we later _change_ which fields are included in the `NameParts` fragment, we a ## Example usage -Let's say we have a blog application that executes several GraphQL operations related to comments (submitting a comment, fetching a post's comments, etc.). These operations probably _all_ include certain fields of a `Comment` type. +Let's say we have a blog application that executes several GraphQL operations related to comments (submitting a comment, fetching a post's comments, etc.). Our application likely has a `Comment` component that is responsible for rendering comment data. -To specify this core set of fields, we can define a fragment on the `Comment` type, like so: +We can define a fragment on the `Comment` type to define the `Comment` component's data requirements, like so: -```js title="fragments.js" +```js title="Comment.js" import { gql } from '@apollo/client'; -export const CORE_COMMENT_FIELDS = gql` - fragment CoreCommentFields on Comment { +export const COMMENT_FRAGMENT = gql` + fragment CommentFragment on Comment { id postedBy { username @@ -65,23 +65,23 @@ export const CORE_COMMENT_FIELDS = gql` `; ``` -> You can declare fragments in any file of your application. The example above `export`s the fragment from a `fragments.js` file. +> The example above `export`s the fragment from the `Comment.js` component file. You can declare fragments in any file of your application, though we recommend this approach of [colocating fragments](#colocating-fragments) with your components. -We can then include the `CoreCommentFields` fragment in a GraphQL operation like so: +We can then include the `CommentFragment` fragment in a GraphQL operation like so: ```jsx {2,5,12} title="PostDetails.jsx" import { gql } from '@apollo/client'; -import { CORE_COMMENT_FIELDS } from './fragments'; +import { COMMENT_FRAGMENT } from './Comment'; export const GET_POST_DETAILS = gql` - ${CORE_COMMENT_FIELDS} + ${COMMENT_FRAGMENT} query CommentsForPost($postId: ID!) { post(postId: $postId) { title body author comments { - ...CoreCommentFields + ...CommentFragment } } } @@ -90,9 +90,9 @@ export const GET_POST_DETAILS = gql` // ...PostDetails component definition... ``` -* We first `import` `CORE_COMMENT_FIELDS` because it's declared in another file. -* We add our fragment definition to the `GET_POST_DETAILS` `gql` template literal via a placeholder (`${CORE_COMMENT_FIELDS}`) -* We include the `CoreCommentFields` fragment in our query with standard `...` notation. +* We first `import` `COMMENT_FRAGMENT` because it's declared in another file. +* We add our fragment definition to the `GET_POST_DETAILS` `gql` template literal via a placeholder (`${COMMENT_FRAGMENT}`) +* We include the `CommentFragment` fragment in our query with standard `...` notation. ## Registering named fragments using `createFragmentRegistry` From f182988d84e855eef3fedae62da421391bc276df Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 10:34:46 -0700 Subject: [PATCH 03/34] Convert fragments page to mdx file --- docs/source/data/{fragments.md => fragments.mdx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/source/data/{fragments.md => fragments.mdx} (100%) diff --git a/docs/source/data/fragments.md b/docs/source/data/fragments.mdx similarity index 100% rename from docs/source/data/fragments.md rename to docs/source/data/fragments.mdx From c7a51c579b7d30cab225373aac57133e88f566af Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 11:04:03 -0700 Subject: [PATCH 04/34] Add section on lazy registering fragments --- docs/source/data/fragments.mdx | 49 +++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index af58bbf557b..9ad07aa92d5 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -94,9 +94,11 @@ export const GET_POST_DETAILS = gql` * We add our fragment definition to the `GET_POST_DETAILS` `gql` template literal via a placeholder (`${COMMENT_FRAGMENT}`) * We include the `CommentFragment` fragment in our query with standard `...` notation. + ## Registering named fragments using `createFragmentRegistry` + -Starting in Apollo Client 3.7, fragments can be registered with your `InMemoryCache` so that they can be referred to by name in any query or `InMemoryCache` operation (such as `cache.readFragment`, `cache.readQuery` and `cache.watch`) without needing to interpolate their declarations. +Starting in Apollo Client 3.7, fragments can be registered with your `InMemoryCache` instance so that they can be referred to by name in any query or `InMemoryCache` operation (such as `cache.readFragment`, `cache.readQuery` and `cache.watch`) without needing to interpolate their declarations. Let's look at an example in React. @@ -192,6 +194,51 @@ function ToDoList() { } ``` +### Lazily registering named fragments + +Fragments do not all need to be defined up-front when the cache is created. Instead, you can register named fragments lazily with the fragment registery. This is especially useful when combined with [colocated fragments](#colocating-fragments) whose fragment definitions are defined in component files. Let's look at an example: + +```tsx title="fragmentRegistry.js" +export const { fragmentRegistry } = createFragmentRegistry(); +``` + +```tsx title="index.js" +import { fragmentRegistry } from "./fragmentRegistry"; + +const client = new ApolloClient({ + uri: "http://localhost:4000/graphql", + cache: new InMemoryCache({ + fragments: fragmentRegistry, + }) +}); +``` + +We create a separate file that creates and exports our fragment registry. This gives us a way to access our shared fragment registry across our application. We use this shared fragment registry with our `InMemoryCache` instance. + +```tsx title="TodoItem.js" +import { gql } from "@apollo/client"; +import { fragmentRegistry } from "./fragmentRegistry"; + +// Register the fragment outside the component to ensure it is registered when this module is loaded. +const ItemFragment = gql` + fragment ItemFragment on Item { + # ... + } +` + +fragmentRegistry.register(ItemFragment); + +function TodoItem() { + // ... +} +``` + +We then import our shared fragment registry into our component file and register our fragment definition. + + + You need to register fragment definitions with the fragment registry before executing operations that use them. This can be problematic when lazy loading component files because the application might not register the fragment definition with the registery until after the query begins executing. Move the fragment definition to a shared file that isn't lazy-loaded. + + ## Colocating fragments The tree-like structure of a GraphQL response resembles the hierarchy of a frontend's rendered components. Because of this similarity, you can use fragments to split query logic up _between_ components, so that each component requests exactly the fields that it uses. This helps you make your component logic more succinct. From 64bb11c537c278ecdb4cbb140fa4760f69ec40e8 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 11:33:26 -0700 Subject: [PATCH 05/34] Rework section on colocated fragments --- docs/source/data/fragments.mdx | 63 +++++++++++++++++----------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 9ad07aa92d5..0d3b239f7f0 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -241,61 +241,60 @@ We then import our shared fragment registry into our component file and register ## Colocating fragments -The tree-like structure of a GraphQL response resembles the hierarchy of a frontend's rendered components. Because of this similarity, you can use fragments to split query logic up _between_ components, so that each component requests exactly the fields that it uses. This helps you make your component logic more succinct. +The tree-like structure of a GraphQL response resembles the hierarchy of a frontend's rendered components. Because of this similarity, you can use fragments to split query logic up _between_ components, so that each component requests exactly the fields that it uses. This helps make your component logic more succinct by combining multiple UI components into a single data fetch. Consider the following view hierarchy for an app: ``` FeedPage -└── Feed - └── FeedEntry - ├── EntryInfo - └── VoteButtons +└── FeedEntry + ├── EntryInfo + └── VoteButtons ``` In this app, the `FeedPage` component executes a query to fetch a list of `FeedEntry` objects. The `EntryInfo` and `VoteButtons` subcomponents need specific fields from the enclosing `FeedEntry` object. ### Creating colocated fragments -A colocated fragment is just like any other fragment, except it's attached to a particular component that uses the fragment's fields. For example, the `VoteButtons` child component of `FeedPage` might use the fields `score` and `vote { choice }` from the `FeedEntry` object: +A colocated fragment is just like any other fragment, except it's defined in the same file as a particular component that uses the fragment's fields. For example, the `VoteButtons` child component of `FeedPage` might use the fields `score` and `vote { choice }` from the `FeedEntry` object: ```js title="VoteButtons.jsx" -VoteButtons.fragments = { - entry: gql` - fragment VoteButtonsFragment on FeedEntry { - score - vote { - choice - } +export const VoteButtonsFragment = gql` + fragment VoteButtonsFragment on FeedEntry { + score + vote { + choice } - `, -}; + } +` ``` After you define a fragment in a child component, the _parent_ component can refer to it in its _own_ colocated fragments, like so: ```js title="FeedEntry.jsx" -FeedEntry.fragments = { - entry: gql` - fragment FeedEntryFragment on FeedEntry { - commentCount - repository { - full_name - html_url - owner { - avatar_url - } +export const FeedEntryFragment = gql` + fragment FeedEntryFragment on FeedEntry { + commentCount + repository { + full_name + html_url + owner { + avatar_url } - ...VoteButtonsFragment - ...EntryInfoFragment } - ${VoteButtons.fragments.entry} - ${EntryInfo.fragments.entry} - `, -}; + ...VoteButtonsFragment + ...EntryInfoFragment + } + ${VoteButtonsFragment} + ${EntryInfoFragment} +` ``` -There's nothing special about the naming of `VoteButtons.fragments.entry` or `EntryInfo.fragments.entry`. Any naming convention works as long as you can retrieve a component's fragments given the component. + +To prevent coupling with deeply nested components, we recommend parent components only add fragments defined by their directly-rendered children. In this example, our `FeedPage` should not use the `EntryInfoFragment` or `VoteButtonsFragment` directly. Instead the `FeedPage` uses the `FeedEntryFragment` fragment colocated with the `FeedEntry` component to combine the `VoteButtonsFragment` and `EntryInfoFragment` fragments into its own fragment. + + +There's nothing special about the naming of `VoteButtonsFragment` or `EntryInfoFragment`. We recommend prefixing the fragment name with the component name to make it easily identifiable when combined with other fragments, however any naming convention works as long as you can retrieve a component's fragments given the component. ### Importing fragments when using Webpack From e14325d35ef4f2c66e6ed06b4caabb9652045189 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 11:36:51 -0700 Subject: [PATCH 06/34] Replace unions and interfaces link with graphql.com reference --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 0d3b239f7f0..12c24b53caa 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -308,7 +308,7 @@ This makes the contents of `someFragment.graphql` available to the current file. ## Using fragments with unions and interfaces -You can define fragments on [unions and interfaces](/apollo-server/schema/unions-interfaces/). +You can define fragments on [unions and interfaces](https://graphql.com/learn/interfaces-and-unions/). Here's an example of a query that includes three in-line fragments: From 10017642e0b0b29af4031d10b17a694050ccfb56 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 11:39:41 -0700 Subject: [PATCH 07/34] Tweak section for unions and interfaces --- docs/source/data/fragments.mdx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 12c24b53caa..22666f7d0e8 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -310,15 +310,12 @@ This makes the contents of `someFragment.graphql` available to the current file. You can define fragments on [unions and interfaces](https://graphql.com/learn/interfaces-and-unions/). -Here's an example of a query that includes three in-line fragments: +Here's an example of a query that includes a shared field and two in-line fragments: ```graphql query AllCharacters { - all_characters { - - ... on Character { - name - } + allCharacters { + name ... on Jedi { side @@ -331,9 +328,9 @@ query AllCharacters { } ``` -The `all_characters` query above returns a list of `Character` objects. The `Character` type is an interface that both the `Jedi` and `Droid` types implement. Each item in the list includes a `side` field if it's an object of type `Jedi`, and it includes a `model` field if it's of type `Droid`. +The `AllCharacters` query above returns a list of `Character` objects. The `Character` type is an interface type that both the `Jedi` and `Droid` types implement. Each item in the list includes a `side` field if it's an object of type `Jedi`, and it includes a `model` field if it's of type `Droid`. Both `Jedi` and `Droid` objects include a `name` field. -**However**, for this query to work, your client needs to understand the polymorphic relationship between the `Character` interface and the types that implement it. To inform the client about these relationships, you can pass a `possibleTypes` option when you initialize your `InMemoryCache`. +**However**, for this query to work, the client needs to understand the polymorphic relationship between the `Character` interface and the types that implement it. To inform the client about these relationships, you must pass a `possibleTypes` option when you initialize your `InMemoryCache` instance. ### Defining `possibleTypes` manually From 444ded214750f4ca57bd556e03d9d5a6ef11202e Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 11:40:19 -0700 Subject: [PATCH 08/34] Remove note about possibleTypes for 3.0 --- docs/source/data/fragments.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 22666f7d0e8..a461055519a 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -334,8 +334,6 @@ The `AllCharacters` query above returns a list of `Character` objects. The `Char ### Defining `possibleTypes` manually -> The `possibleTypes` option is available in Apollo Client 3.0 and later. - You can pass a `possibleTypes` option to the `InMemoryCache` constructor to specify supertype-subtype relationships in your schema. This object maps the name of an interface or union type (the supertype) to the types that implement or belong to it (the subtypes). Here's an example `possibleTypes` declaration: From ba9abde3ae3976b795de1cda48062b71c6f81164 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 11:41:35 -0700 Subject: [PATCH 09/34] Tweak intro sentence in manual possible types --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index a461055519a..ea53447e29a 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -334,7 +334,7 @@ The `AllCharacters` query above returns a list of `Character` objects. The `Char ### Defining `possibleTypes` manually -You can pass a `possibleTypes` option to the `InMemoryCache` constructor to specify supertype-subtype relationships in your schema. This object maps the name of an interface or union type (the supertype) to the types that implement or belong to it (the subtypes). +Use the `possibleTypes` option to the `InMemoryCache` constructor to specify supertype-subtype relationships in your schema. This object maps the name of an interface or union type (the supertype) to the types that implement or belong to it (the subtypes). Here's an example `possibleTypes` declaration: From 2a2b8e16581e91d9ec9bee8171b336e69897b263 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 11:44:03 -0700 Subject: [PATCH 10/34] Minor tweak to manual types --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index ea53447e29a..b525afc1c43 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -350,7 +350,7 @@ const cache = new InMemoryCache({ This example lists three interfaces (`Character`, `Test`, and `Snake`) and the object types that implement them. -If your schema includes only a few unions and interfaces, you can probably specify your `possibleTypes` manually without issue. However, as your schema grows in size and complexity, you should consider [generating `possibleTypes` automatically from your schema](#generating-possibletypes-automatically). +If your schema includes only a few unions and interfaces, you can probably specify your `possibleTypes` manually without issue. However, as your schema grows in size and complexity, you should instead [generate `possibleTypes` automatically from your schema](#generating-possibletypes-automatically). ### Generating `possibleTypes` automatically From b15a3f06ad3853adcde08d49acf9d53c71ce883a Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 11:51:09 -0700 Subject: [PATCH 11/34] Add section on GraphQL Codegen with with possibleTypes --- docs/source/data/fragments.mdx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index b525afc1c43..e29f953b67e 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -354,7 +354,7 @@ If your schema includes only a few unions and interfaces, you can probably speci ### Generating `possibleTypes` automatically -The following example script translates a GraphQL introspection query into a `possibleTypes` configuration object: +The following script translates a GraphQL introspection query into a `possibleTypes` configuration object: ```js const fetch = require('cross-fetch'); @@ -410,6 +410,20 @@ const cache = new InMemoryCache({ }); ``` +### Generating `possibleTypes` with GraphQL Codegen + +[GraphQL Codegen](https://the-guild.dev/graphql/codegen) has the ability to generate `possibleTypes` for you using the [`fragment-matcher` plugin](https://the-guild.dev/graphql/codegen/plugins/other/fragment-matcher). Follow the guide in the [fragment matcher plugin docs](https://the-guild.dev/graphql/codegen/plugins/other/fragment-matcher) to configure GraphQL Codegen to write a JSON file that contains `possibleTypes`. + +You can then `import` the generated `possibleTypes` JSON module into the file where you create your `InMemoryCache`: + +```ts +import possibleTypes from './path/to/possibleTypes.json'; + +const cache = new InMemoryCache({ + possibleTypes, +}); +``` + ## `useFragment` From d903d37a4da27f244bcdc1c293c52b2d98829953 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 12:30:37 -0700 Subject: [PATCH 12/34] Tweak note on experimental version --- docs/source/data/fragments.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index e29f953b67e..9c8dfad37f0 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -434,7 +434,9 @@ The `useFragment` hook represents a lightweight live binding into the Apollo Cli **The `useQuery` hook remains the primary hook responsible for querying and populating data in the cache** ([see the API reference](../api/react/hooks#usequery)). As a result, the component reading the fragment data via `useFragment` is still subscribed to all changes in the query data, but receives updates only when that fragment's specific data change. -> **Note**: this hook was introduced in `3.7.0` as experimental but stabilized in `3.8.0`. In `3.7.x` and `3.8.0-alpha.x` releases, this hook is exported as `useFragment_experimental`. Starting with `3.8.0-beta.0` and greater the `_experimental` suffix was removed in its named export. + +`useFragment` was introduced as an experimental hook in version `3.7.0` under the named export `useFragment_experimental`. Starting with `3.8.0-beta.0` and greater the `_experimental` suffix was removed in its named export. + ### Example From 75f9fbaf9dc4df7c970d768e7560b960890b87e2 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 12:48:40 -0700 Subject: [PATCH 13/34] Tweak `useFragment` section --- docs/source/data/fragments.mdx | 74 ++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 9c8dfad37f0..ed11357a012 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -450,7 +450,7 @@ const ItemFragment = gql` `; ``` -We can first use the `useQuery` hook to retrieve a list of items with `id`s as well as any fields selected on the named `ItemFragment` fragment by spreading `ItemFragment` inside of `list` in `ListQuery`. +We can first use the `useQuery` hook to retrieve a list of items with `id`s as well as any fields selected on the named `ItemFragment` fragment by including `ItemFragment` in the `list` field in the `GetItemList` query. ```jsx const listQuery = gql` @@ -469,32 +469,90 @@ function List() { return (
    {data?.list.map(item => ( - + ))}
); } ``` -> **Note:** Instead of interpolating fragments within each query document, we can use Apollo Client's `createFragmentRegistry` method to pre-register named fragments with our `InMemoryCache`. This allows Apollo Client to include the definitions for registered fragments in the document sent over the network before the request is sent. For more information, see [Registering named fragments using `createFragmentRegistry`](#registering-named-fragments-using-createfragmentregistry). + +Instead of interpolating fragments within each query document, you can use Apollo Client's `createFragmentRegistry` method to pre-register named fragments with `InMemoryCache`. This allows Apollo Client to include the definitions for registered fragments in the document sent over the network before the request is sent. For more information, see [Registering named fragments using `createFragmentRegistry`](#registering-named-fragments-using-createfragmentregistry). + We can then use `useFragment` from within the `` component to create a live binding for each item by providing the `fragment` document, `fragmentName` and object reference via `from`. -```jsx + + +```tsx function Item(props: { id: number }) { const { complete, data } = useFragment({ fragment: ItemFragment, fragmentName: "ItemFragment", from: { __typename: "Item", - id: props.id, - }, + id: props.id + } + }); + + return
  • {complete ? data.text : "incomplete"}
  • ; +} +``` + +```jsx +function Item(props) { + const { complete, data } = useFragment({ + fragment: ItemFragment, + fragmentName: "ItemFragment", + from: { + __typename: "Item", + id: props.id + } }); return
  • {complete ? data.text : "incomplete"}
  • ; } ``` -> `useFragment` can be used in combination with the `@nonreactive` directive in cases where list items should react to individual cache updates without rerendering the entire list. For more information, see the [`@nonreactive` docs](/react/data/directives#nonreactive). +
    + + +You may omit the `fragmentName` option when your fragment definition only includes a single fragment. + + +You may instead prefer to pass the whole `item` as a prop to the `Item` component. This makes the `from` option more concise. + + + +```tsx +function Item(props: { item: { __typename: 'Item', id: number }}) { + const { complete, data } = useFragment({ + fragment: ItemFragment, + fragmentName: "ItemFragment", + from: item + }); + + return
  • {complete ? data.text : "incomplete"}
  • ; +} +``` + +```jsx +function Item(props) { + const { complete, data } = useFragment({ + fragment: ItemFragment, + fragmentName: "ItemFragment", + from: item + }); + + return
  • {complete ? data.text : "incomplete"}
  • ; +} +``` + +
    + + + +`useFragment` can be used in combination with the `@nonreactive` directive in cases where list items should react to individual cache updates without rerendering the entire list. For more information, see the [`@nonreactive` docs](/react/data/directives#nonreactive). + -[See the API reference for more details.](../api/react/hooks#usefragment) +See the [API reference](../api/react/hooks#usefragment) for more details on the supported options. From b75556bed57624faf7bc6315dd58eece820a5664 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 12:52:06 -0700 Subject: [PATCH 14/34] Tweak intro sentence --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index ed11357a012..0a7458af89c 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -3,7 +3,7 @@ title: Fragments description: Share fields between operations --- -A [GraphQL fragment](http://graphql.org/learn/queries/#fragments) is a piece of logic that can be shared between multiple queries and mutations. Fragments are especially useful when used as [colocated fragments](#colocating-fragments) with components to define their data requirements. +A [GraphQL fragment](http://graphql.org/learn/queries/#fragments) is a piece of logic that can be shared between multiple queries and mutations. Fragments are especially useful when [colocated with components](#colocating-fragments) to define the component's data requirements. Here's the declaration of a `NameParts` fragment that can be used with any `Person` object: From 79bd01e6909024b42ad40f0b77f63e90e74c8234 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Thu, 21 Nov 2024 14:01:59 -0700 Subject: [PATCH 15/34] Ensure code languages match their filename --- docs/source/data/fragments.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 0a7458af89c..bd8d2ac033a 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -198,11 +198,11 @@ function ToDoList() { Fragments do not all need to be defined up-front when the cache is created. Instead, you can register named fragments lazily with the fragment registery. This is especially useful when combined with [colocated fragments](#colocating-fragments) whose fragment definitions are defined in component files. Let's look at an example: -```tsx title="fragmentRegistry.js" +```js title="fragmentRegistry.js" export const { fragmentRegistry } = createFragmentRegistry(); ``` -```tsx title="index.js" +```js title="index.js" import { fragmentRegistry } from "./fragmentRegistry"; const client = new ApolloClient({ @@ -215,7 +215,7 @@ const client = new ApolloClient({ We create a separate file that creates and exports our fragment registry. This gives us a way to access our shared fragment registry across our application. We use this shared fragment registry with our `InMemoryCache` instance. -```tsx title="TodoItem.js" +```jsx title="TodoItem.jsx" import { gql } from "@apollo/client"; import { fragmentRegistry } from "./fragmentRegistry"; @@ -338,7 +338,7 @@ Use the `possibleTypes` option to the `InMemoryCache` constructor to specify sup Here's an example `possibleTypes` declaration: -```ts +```js const cache = new InMemoryCache({ possibleTypes: { Character: ["Jedi", "Droid"], From 58d29421f079777124620857bab70f61419ecad4 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 10:41:07 -0700 Subject: [PATCH 16/34] Use mermaid diagram for hierarchy --- docs/source/data/fragments.mdx | 38 +++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index bd8d2ac033a..7feca169865 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -245,11 +245,39 @@ The tree-like structure of a GraphQL response resembles the hierarchy of a front Consider the following view hierarchy for an app: -``` -FeedPage -└── FeedEntry - ├── EntryInfo - └── VoteButtons +```mermaid +graph TD + subgraph FeedPageGroup[" "] + direction TB + FeedPage[<FeedPage />] + FeedQuery["query FeedQuery { feed { ...FeedEntryFragment } }"] + FeedPage ~~~ FeedQuery + end + + subgraph FeedEntryGroup[" "] + direction TB + FeedEntry["<FeedEntry />"] + FeedEntryFragment["fragment FeedEntry { ...EntryInfoFragment ...VoteButtonsFragment }"] + FeedEntry ~~~ FeedEntryFragment + end + + subgraph EntryInfoGroup[" "] + direction TB + EntryInfo["<EntryInfo />"] + EntryInfoFragment["fragment EntryInfo { ... }"] + EntryInfo ~~~ EntryInfoFragment + end + + subgraph VoteButtonsGroup[" "] + direction TB + VoteButtons["<VoteButtons />"] + VoteButtonsFragment["fragment VoteButtons { ... }"] + VoteButtons ~~~ VoteButtonsFragment + end + + FeedPageGroup --> FeedEntryGroup + FeedEntryGroup --> EntryInfoGroup + FeedEntryGroup --> VoteButtonsGroup ``` In this app, the `FeedPage` component executes a query to fetch a list of `FeedEntry` objects. The `EntryInfo` and `VoteButtons` subcomponents need specific fields from the enclosing `FeedEntry` object. From aaaa966896459c80cdd7e45c4e8f6135dafc725b Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 10:41:45 -0700 Subject: [PATCH 17/34] Remove unneeded prefix about version --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 7feca169865..4fc3cd2ffa5 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -98,7 +98,7 @@ export const GET_POST_DETAILS = gql` ## Registering named fragments using `createFragmentRegistry`
    -Starting in Apollo Client 3.7, fragments can be registered with your `InMemoryCache` instance so that they can be referred to by name in any query or `InMemoryCache` operation (such as `cache.readFragment`, `cache.readQuery` and `cache.watch`) without needing to interpolate their declarations. +Fragments can be registered with your `InMemoryCache` instance so that they can be referred to by name in any query or `InMemoryCache` operation (such as `cache.readFragment`, `cache.readQuery` and `cache.watch`) without needing to interpolate their declarations. Let's look at an example in React. From 2972f02f6a5b279279773badc65dc03bd1c27623 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 13:23:39 -0700 Subject: [PATCH 18/34] Add note about fragments --- docs/source/data/fragments.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 4fc3cd2ffa5..dd258c262a6 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -100,6 +100,10 @@ export const GET_POST_DETAILS = gql` Fragments can be registered with your `InMemoryCache` instance so that they can be referred to by name in any query or `InMemoryCache` operation (such as `cache.readFragment`, `cache.readQuery` and `cache.watch`) without needing to interpolate their declarations. + +We do not recommend using the fragment registry when using the GraphQL Codegen [client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client) with the generated `graphql` function. The client preset precompiles GraphQL queries and includes the fragment definition for you. + + Let's look at an example in React. ```js title="index.js" {7-12} From 7c7cca8087c81da6faba03769f98f27e960a15f0 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 13:28:02 -0700 Subject: [PATCH 19/34] Move fragment definition to the bottom --- docs/source/data/fragments.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index dd258c262a6..64ae285e327 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -74,7 +74,6 @@ import { gql } from '@apollo/client'; import { COMMENT_FRAGMENT } from './Comment'; export const GET_POST_DETAILS = gql` - ${COMMENT_FRAGMENT} query CommentsForPost($postId: ID!) { post(postId: $postId) { title @@ -85,6 +84,8 @@ export const GET_POST_DETAILS = gql` } } } + + ${COMMENT_FRAGMENT} `; // ...PostDetails component definition... From 7a5666d20e4e9e016d392bb4ed09db07660259d8 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 13:28:26 -0700 Subject: [PATCH 20/34] Rename query in example --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 64ae285e327..c9d7f4905d3 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -74,7 +74,7 @@ import { gql } from '@apollo/client'; import { COMMENT_FRAGMENT } from './Comment'; export const GET_POST_DETAILS = gql` - query CommentsForPost($postId: ID!) { + query GetPostDetails($postId: ID!) { post(postId: $postId) { title body From 6d72bab2222c88a8953c86b11967fe419fa22f28 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 13:29:01 -0700 Subject: [PATCH 21/34] Remove export on the query --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index c9d7f4905d3..2f42ab834a8 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -73,7 +73,7 @@ We can then include the `CommentFragment` fragment in a GraphQL operation like s import { gql } from '@apollo/client'; import { COMMENT_FRAGMENT } from './Comment'; -export const GET_POST_DETAILS = gql` +const GET_POST_DETAILS = gql` query GetPostDetails($postId: ID!) { post(postId: $postId) { title From da619919ebffa03d59e19e92a48f047ced8d2a76 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 13:29:41 -0700 Subject: [PATCH 22/34] Fix highlighting --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 2f42ab834a8..0281c9c2421 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -69,7 +69,7 @@ export const COMMENT_FRAGMENT = gql` We can then include the `CommentFragment` fragment in a GraphQL operation like so: -```jsx {2,5,12} title="PostDetails.jsx" +```jsx {2,11,16} title="PostDetails.jsx" import { gql } from '@apollo/client'; import { COMMENT_FRAGMENT } from './Comment'; From 972ce056f4ccf563426427f4caeb30b0c29fb43f Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 13:32:38 -0700 Subject: [PATCH 23/34] Tweak sentence on note about client preset --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 0281c9c2421..28e0568e3a3 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -102,7 +102,7 @@ const GET_POST_DETAILS = gql` Fragments can be registered with your `InMemoryCache` instance so that they can be referred to by name in any query or `InMemoryCache` operation (such as `cache.readFragment`, `cache.readQuery` and `cache.watch`) without needing to interpolate their declarations. -We do not recommend using the fragment registry when using the GraphQL Codegen [client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client) with the generated `graphql` function. The client preset precompiles GraphQL queries and includes the fragment definition for you. +We do not recommend using the fragment registry when using the `graphql` function generated by the GraphQL Codegen [client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client). The client preset creates precompiled GraphQL documents which include the fragment definition. Let's look at an example in React. From 9d65709e6d129dcf772580f34223f962920345fc Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 13:39:38 -0700 Subject: [PATCH 24/34] Tweak again --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 28e0568e3a3..e87358c5545 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -102,7 +102,7 @@ const GET_POST_DETAILS = gql` Fragments can be registered with your `InMemoryCache` instance so that they can be referred to by name in any query or `InMemoryCache` operation (such as `cache.readFragment`, `cache.readQuery` and `cache.watch`) without needing to interpolate their declarations. -We do not recommend using the fragment registry when using the `graphql` function generated by the GraphQL Codegen [client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client). The client preset creates precompiled GraphQL documents which include the fragment definition. +We do not recommend using the fragment registry when using the `graphql` function generated by the GraphQL Codegen [client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client). The client preset creates precompiled GraphQL documents which already include the fragment definition in them. Let's look at an example in React. From 3f9dceb21ccbad1ef5118a283d1f797c755136d9 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 13:45:00 -0700 Subject: [PATCH 25/34] Use screaming snake case for all fragments --- docs/source/data/fragments.mdx | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index e87358c5545..5933f1fb1e9 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -175,7 +175,7 @@ const client = new ApolloClient({ The local version of the `ExtraFields` fragment declared in `ItemList.jsx` takes precedence over the `ExtraFields` originally registered with the `InMemoryCache`. Thus, its definition will be used when the `ExtraFields` fragment spread is parsed inside of the registered `ItemFragment` _only when `GetItemList` query is executed_, because explicit definitions take precedence over registered fragments. ```jsx title="ItemList.jsx" {8-10,17} -const listQuery = gql` +const GET_ITEM_LIST = gql` query GetItemList { list { ...ItemFragment @@ -187,7 +187,7 @@ const listQuery = gql` } `; function ToDoList() { - const { data } = useQuery(listQuery); + const { data } = useQuery(GET_ITEM_LIST); return (
      {data?.list.map((item) => ( @@ -225,13 +225,13 @@ import { gql } from "@apollo/client"; import { fragmentRegistry } from "./fragmentRegistry"; // Register the fragment outside the component to ensure it is registered when this module is loaded. -const ItemFragment = gql` +const ITEM_FRAGMENT = gql` fragment ItemFragment on Item { # ... } ` -fragmentRegistry.register(ItemFragment); +fragmentRegistry.register(ITEM_FRAGMENT); function TodoItem() { // ... @@ -292,7 +292,7 @@ In this app, the `FeedPage` component executes a query to fetch a list of `FeedE A colocated fragment is just like any other fragment, except it's defined in the same file as a particular component that uses the fragment's fields. For example, the `VoteButtons` child component of `FeedPage` might use the fields `score` and `vote { choice }` from the `FeedEntry` object: ```js title="VoteButtons.jsx" -export const VoteButtonsFragment = gql` +export const VOTE_BUTTONS_FRAGMENT = gql` fragment VoteButtonsFragment on FeedEntry { score vote { @@ -305,7 +305,7 @@ export const VoteButtonsFragment = gql` After you define a fragment in a child component, the _parent_ component can refer to it in its _own_ colocated fragments, like so: ```js title="FeedEntry.jsx" -export const FeedEntryFragment = gql` +export const FEED_ENTRY_FRAGMENT = gql` fragment FeedEntryFragment on FeedEntry { commentCount repository { @@ -318,8 +318,8 @@ export const FeedEntryFragment = gql` ...VoteButtonsFragment ...EntryInfoFragment } - ${VoteButtonsFragment} - ${EntryInfoFragment} + ${VOTE_BUTTONS_FRAGMENT} + ${ENTRY_INFO_FRAGMENT} ` ``` @@ -476,7 +476,7 @@ The `useFragment` hook represents a lightweight live binding into the Apollo Cli Given the following fragment definition: ```js -const ItemFragment = gql` +const ITEM_FRAGMENT = gql` fragment ItemFragment on Item { text } @@ -493,7 +493,8 @@ const listQuery = gql` ...ItemFragment } } - ${ItemFragment} + + ${ITEM_FRAGMENT} `; function List() { @@ -520,7 +521,7 @@ We can then use `useFragment` from within the `` component to create a liv ```tsx function Item(props: { id: number }) { const { complete, data } = useFragment({ - fragment: ItemFragment, + fragment: ITEM_FRAGMENT, fragmentName: "ItemFragment", from: { __typename: "Item", @@ -535,7 +536,7 @@ function Item(props: { id: number }) { ```jsx function Item(props) { const { complete, data } = useFragment({ - fragment: ItemFragment, + fragment: ITEM_FRAGMENT, fragmentName: "ItemFragment", from: { __typename: "Item", @@ -572,7 +573,7 @@ function Item(props: { item: { __typename: 'Item', id: number }}) { ```jsx function Item(props) { const { complete, data } = useFragment({ - fragment: ItemFragment, + fragment: ITEM_FRAGMENT, fragmentName: "ItemFragment", from: item }); From b36dd7794c4a46a262e71b5bacbfdf02fe549825 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 13:47:19 -0700 Subject: [PATCH 26/34] Tweak comment --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 5933f1fb1e9..52dd360a8d1 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -224,7 +224,7 @@ We create a separate file that creates and exports our fragment registry. This g import { gql } from "@apollo/client"; import { fragmentRegistry } from "./fragmentRegistry"; -// Register the fragment outside the component to ensure it is registered when this module is loaded. +// Define the fragment outside the component to ensure it gets registered when this module is loaded. const ITEM_FRAGMENT = gql` fragment ItemFragment on Item { # ... From 506bd9d4e4635460b92a29a778b132294a18b0ad Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 22:05:09 -0700 Subject: [PATCH 27/34] Improve description of fragment Co-authored-by: Maria Elisabeth Schreiber --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 52dd360a8d1..9e57f9420ed 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -3,7 +3,7 @@ title: Fragments description: Share fields between operations --- -A [GraphQL fragment](http://graphql.org/learn/queries/#fragments) is a piece of logic that can be shared between multiple queries and mutations. Fragments are especially useful when [colocated with components](#colocating-fragments) to define the component's data requirements. +A [GraphQL fragment](http://graphql.org/learn/queries/#fragments) is a set of fields you can reuse across multiple queries and mutations. Fragments are especially useful when [colocated with components](#colocating-fragments) to define the component's data requirements. Here's the declaration of a `NameParts` fragment that can be used with any `Person` object: From af38d4d657d59cee70933b0a687769d9bd5cd916 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 22:22:46 -0700 Subject: [PATCH 28/34] Change how fragments are included and remove the extra blockquote --- docs/source/data/fragments.mdx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 9e57f9420ed..3b176374b69 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -16,7 +16,7 @@ fragment NameParts on Person { Every fragment includes a subset of the fields that belong to its associated type. In the above example, the `Person` type must declare `firstName` and `lastName` fields for the `NameParts` fragment to be valid. -We can now include the `NameParts` fragment in any number of queries and mutations that refer to `Person` objects, like so: +You can include the `NameParts` fragment in any number of operations that refer to `Person` objects by using the spread operator (`...`), followed by the fragment name: ```graphql query GetPerson { @@ -27,8 +27,6 @@ query GetPerson { } ``` ->You precede an included fragment with three periods (`...`), much like JavaScript [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax). - Based on our `NameParts` definition, the above query is equivalent to: ```graphql From 2a0ffeff0acd41a4027cb5b1e1dc75da226909cc Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 22:27:45 -0700 Subject: [PATCH 29/34] Tweak how fragment changes are described Co-authored-by: Maria Elisabeth Schreiber --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 3b176374b69..db23ef13707 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -39,7 +39,7 @@ query GetPerson { } ``` -If we later _change_ which fields are included in the `NameParts` fragment, we automatically change which fields are included in operations that _use_ the fragment. This reduces the effort required to keep fields consistent across a set of operations. +Changes to the `NameParts` fragment automatically update the fields included in any operations that use it. This reduces the effort required to keep fields consistent across a set of operations. ## Example usage From 702157a08b9c5ca7c0ee23afa9185cbe7fcff4f8 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 22:30:31 -0700 Subject: [PATCH 30/34] Remove passive voice --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index db23ef13707..e31d76bcab0 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -97,7 +97,7 @@ const GET_POST_DETAILS = gql` ## Registering named fragments using `createFragmentRegistry` -Fragments can be registered with your `InMemoryCache` instance so that they can be referred to by name in any query or `InMemoryCache` operation (such as `cache.readFragment`, `cache.readQuery` and `cache.watch`) without needing to interpolate their declarations. +Registering fragments with your `InMemoryCache` instance lets you refer to them by name in queries and cache operations (for example, `cache.readFragment`, `cache.readQuery`, and `cache.watch`) without needing to interpolate their declarations. We do not recommend using the fragment registry when using the `graphql` function generated by the GraphQL Codegen [client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client). The client preset creates precompiled GraphQL documents which already include the fragment definition in them. From f2706d67411933c151bd7ac29a2cf8e6a782aaae Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 22:34:58 -0700 Subject: [PATCH 31/34] Improve verbiage throughout Co-authored-by: Maria Elisabeth Schreiber --- docs/source/data/fragments.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index e31d76bcab0..6b6cb403b38 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -100,7 +100,7 @@ const GET_POST_DETAILS = gql` Registering fragments with your `InMemoryCache` instance lets you refer to them by name in queries and cache operations (for example, `cache.readFragment`, `cache.readQuery`, and `cache.watch`) without needing to interpolate their declarations. -We do not recommend using the fragment registry when using the `graphql` function generated by the GraphQL Codegen [client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client). The client preset creates precompiled GraphQL documents which already include the fragment definition in them. +We do not recommend using the fragment registry when using the `graphql` function generated by the GraphQL Codegen [client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client). The client preset creates precompiled GraphQL documents that already include fragment definitions. Let's look at an example in React. @@ -122,7 +122,7 @@ const client = new ApolloClient({ }); ``` -Since `ItemFragment` was registered with `InMemoryCache`, it can be referenced by name as seen below with the fragment spread inside of the `GetItemList` query. +Since `ItemFragment` was registered with `InMemoryCache`, it can be referenced by name, as seen below, with the fragment spread inside of the `GetItemList` query. ```jsx title="ItemList.jsx" {4,13} const listQuery = gql` @@ -146,7 +146,7 @@ function ToDoList() { ### Overriding registered fragments with local versions -Queries can declare their own local versions of named fragments which will take precendence over ones registered via `createFragmentRegistry`, even if the local fragment is only indirectly referenced by other registered fragments. Take the following example: +Queries can declare their own local versions of named fragments which take precedence over ones registered via `createFragmentRegistry`, even if the local fragment is only indirectly referenced by other registered fragments. Take the following example: ```js title="index.js" {7-17} import { ApolloClient, gql, InMemoryCache } from "@apollo/client"; @@ -199,7 +199,7 @@ function ToDoList() { ### Lazily registering named fragments -Fragments do not all need to be defined up-front when the cache is created. Instead, you can register named fragments lazily with the fragment registery. This is especially useful when combined with [colocated fragments](#colocating-fragments) whose fragment definitions are defined in component files. Let's look at an example: +Fragments don't need to be defined upfront when the cache is created. Instead, you can register named fragments lazily with the fragment registry. This is especially useful when combined with [colocated fragments](#colocating-fragments) whose fragment definitions are defined in component files. Let's look at an example: ```js title="fragmentRegistry.js" export const { fragmentRegistry } = createFragmentRegistry(); @@ -216,7 +216,7 @@ const client = new ApolloClient({ }); ``` -We create a separate file that creates and exports our fragment registry. This gives us a way to access our shared fragment registry across our application. We use this shared fragment registry with our `InMemoryCache` instance. +We create a separate file that creates and exports our fragment registry. This lets us access our shared fragment registry across our application. We use this shared fragment registry with our `InMemoryCache` instance. ```jsx title="TodoItem.jsx" import { gql } from "@apollo/client"; @@ -325,7 +325,7 @@ export const FEED_ENTRY_FRAGMENT = gql` To prevent coupling with deeply nested components, we recommend parent components only add fragments defined by their directly-rendered children. In this example, our `FeedPage` should not use the `EntryInfoFragment` or `VoteButtonsFragment` directly. Instead the `FeedPage` uses the `FeedEntryFragment` fragment colocated with the `FeedEntry` component to combine the `VoteButtonsFragment` and `EntryInfoFragment` fragments into its own fragment. -There's nothing special about the naming of `VoteButtonsFragment` or `EntryInfoFragment`. We recommend prefixing the fragment name with the component name to make it easily identifiable when combined with other fragments, however any naming convention works as long as you can retrieve a component's fragments given the component. +There's nothing special about the naming of `VoteButtonsFragment` or `EntryInfoFragment`. We recommend prefixing the fragment name with the component name to make it easily identifiable when combined with other fragments. However any naming convention works as long as you can retrieve a component's fragments given the component. ### Importing fragments when using Webpack From c1264755bb6fad1b66f7fbf860d13b245102a8c5 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 22:36:59 -0700 Subject: [PATCH 32/34] Tweak statement about extra fields --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 6b6cb403b38..5b2172fddf3 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -170,7 +170,7 @@ const client = new ApolloClient({ }); ``` -The local version of the `ExtraFields` fragment declared in `ItemList.jsx` takes precedence over the `ExtraFields` originally registered with the `InMemoryCache`. Thus, its definition will be used when the `ExtraFields` fragment spread is parsed inside of the registered `ItemFragment` _only when `GetItemList` query is executed_, because explicit definitions take precedence over registered fragments. +The local version of the `ExtraFields` fragment declared in `ItemList.jsx` takes precedence over the `ExtraFields` fragment originally registered with the `InMemoryCache` instance. Thus, the local definition will _only be used when `GetItemList` query is executed_, because explicit definitions take precedence over registered fragments. ```jsx title="ItemList.jsx" {8-10,17} const GET_ITEM_LIST = gql` From f0945d743bb4fe46a4ae128df16cfc71d69873e2 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 22:51:48 -0700 Subject: [PATCH 33/34] Tweak section on fragment colocation --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 5b2172fddf3..4306e7076ce 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -244,7 +244,7 @@ We then import our shared fragment registry into our component file and register ## Colocating fragments -The tree-like structure of a GraphQL response resembles the hierarchy of a frontend's rendered components. Because of this similarity, you can use fragments to split query logic up _between_ components, so that each component requests exactly the fields that it uses. This helps make your component logic more succinct by combining multiple UI components into a single data fetch. +The tree-like structure of a GraphQL response resembles the hierarchy of a frontend's rendered components. Because of this similarity, you can use fragments to split query logic _between_ components, so each component requests exactly the fields it needs. This helps make your component logic more succinct by combining multiple UI components into a single data fetch. Consider the following view hierarchy for an app: From db866e2aa447fe889ca1bbfef3550cda8b1ecfe8 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 25 Nov 2024 22:57:51 -0700 Subject: [PATCH 34/34] Remove unneeded usage of `we` --- docs/source/data/fragments.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/data/fragments.mdx b/docs/source/data/fragments.mdx index 4306e7076ce..0614cee93b9 100644 --- a/docs/source/data/fragments.mdx +++ b/docs/source/data/fragments.mdx @@ -329,7 +329,7 @@ There's nothing special about the naming of `VoteButtonsFragment` or `EntryInfoF ### Importing fragments when using Webpack -When loading `.graphql` files with [graphql-tag/loader](https://github.com/apollographql/graphql-tag/blob/main/loader.js), we can include fragments using `import` statements. For example: +When loading `.graphql` files with [graphql-tag/loader](https://github.com/apollographql/graphql-tag/blob/main/loader.js), include fragments using `import` statements. For example: ```graphql #import "./someFragment.graphql"