Fragments and Reusable Query Parts

intermediate
10 min

Fragments and Reusable Query Parts

As apps grow, the same groups of fields appear in query after query: every card that shows a user wants id, name, and avatar. Copy-pasting those selections invites drift and bugs. GraphQL solves this with fragments: named, typed, reusable selection sets. This lesson covers fragment syntax, inline fragments, and the colocation pattern that modern clients are built around.

Defining and Spreading Fragments

A fragment declares a selection set on a specific type, and is spread into queries with ...:

graphql
fragment UserCard on User { id name avatar(size: 64) } query Dashboard { me { ...UserCard } post(id: "7") { title author { ...UserCard } } }

The server expands each spread as if the fields were written inline. Change UserCard once and every usage updates. Fragments can spread other fragments, but cycles are forbidden and validated against, and every declared fragment must be used.

Type Safety Built In

The on User type condition matters: spreading UserCard inside a Post selection is a validation error caught before execution. Fragments are not text templates; they participate fully in type checking, which is why they beat string concatenation for composing queries.

Inline Fragments

Sometimes you need a one-off type condition without naming a fragment, most commonly when a field returns an interface or union (fully covered next lesson):

graphql
query Search { search(term: "graphql") { ... on Post { title } ... on User { name } } }

The ... on Type { } syntax applies those fields only when the runtime object is of that type. Add __typename to the selection so the client can tell which case it received.

Colocation: Fragments as Component Contracts

The deepest use of fragments is architectural. In React codebases using Relay or Apollo, each component declares a fragment describing exactly the data it renders, colocated in the same file:

js
// UserCard.jsx export const USER_CARD_FRAGMENT = gql` fragment UserCard on User { id name avatar(size: 64) } `;

Pages then compose their query from the fragments of the components they render. The benefits compound:

  • A component never receives less data than it needs (no silent undefined props).
  • Deleting a component deletes its data requirements; queries never accumulate dead fields.
  • Reviewers see data changes next to render changes in the same diff.

Fragments and Caching

Normalized client caches key objects by __typename plus id. Because fragments encourage consistently selecting id everywhere an entity appears, cache updates after mutations propagate to every component automatically. This is a practical reason to include id in every fragment even if the UI never displays it.

Key Takeaways

  • Fragments are named selection sets bound to a type, spread with ...Name, and fully type-checked.
  • Inline fragments (... on Type) branch on runtime type, essential for interfaces and unions.
  • Colocating one fragment per UI component keeps data requirements exact and maintainable.
  • Always select id (and rely on __typename) so normalized caches work for you.

Next lesson: Interfaces, Unions and Enums, the type-system features that make inline fragments shine.

Fragments and Reusable Query Parts - GraphQL | CodeYourCraft | CodeYourCraft