A GraphQL fragment is a named, reusable set of fields for one type, written as fragment Name on Type and pulled into a query with ...Name. An inline fragment, written ... on Type, has no name and picks fields only when the result is that concrete type, which is how you query unions and interfaces.
| Form | Syntax | Use it for |
|---|---|---|
| Named fragment | fragment UserCard on User { ... } | Sharing one field list across queries |
| Spread | ...UserCard | Including a named fragment's fields |
| Inline fragment | ... on Photo { url } | Fields of one member of a union or interface |
| Inline without type | ... @include(if: $full) { bio } | Applying a directive to a group of fields |
| Type name | __typename | Telling union members apart in the response |
Updated
Tick the fields you want in the builder and it writes the query for you, once with a named fragment and once with the fields typed inline, so you can see they ask for the same data. Turn on the search results option to add inline fragments over a union.
query Profile($id: ID!) {
user(id: $id) {
...UserCard
}
}
fragment UserCard on User {
id
name
avatarUrl
}SearchResult can be a User or a Photo, so a selection on it needs inline fragments to reach fields of either member.
type User {
id: ID!
name: String!
avatarUrl: String
email: String
createdAt: String!
}
type Photo {
id: ID!
url: String!
width: Int!
}
union SearchResult = User | Photo
type Query {
user(id: ID!): User
search(text: String!): [SearchResult!]!
}Each item carries only the fields of its own branch, plus __typename.
{
"data": {
"search": [
{ "__typename": "User", "id": "42", "name": "Ada" },
{ "__typename": "Photo", "url": "/p/lake.jpg", "width": 1200 }
]
}
}The type name is the safe way to tell the members apart; checking for a field can break when a type later gains it.
for (const item of data.search) {
switch (item.__typename) {
case "User":
renderUser(item);
break;
case "Photo":
renderPhoto(item);
break;
}
}
Suppose a profile header, a comment and a member list all show a name and an avatar. Typing those fields three times invites drift: one copy gains a field the others lack. A fragment on User holds the list once and each query spreads it.
Component-based apps take this further. Each component declares the fragment it needs, and the page query spreads the fragments of the components it renders, so data needs live beside the code that uses them.
The on Type part is the type condition. For a named fragment it says which type the fields belong to. For an inline fragment inside a union field, it makes those fields apply only when the object is that type.
A search that returns users, posts and photos is the classic case. The selection lists ... on User, ... on Post and ... on Photo, each with its own fields, and __typename tells the client which branch each result took.
No. A fragment is a writing aid for the query. The server expands it, and the response looks exactly as if you had typed the fields out. If two spreads select the same field, it appears once.
When a field returns a union or an interface and you need fields that only some member types have. graphql.org shows this with a hero that may be a Droid with primaryFunction or a Human with height.
Only where it could apply. A fragment on an interface can be spread inside any object type that implements it, but a fragment on User spread inside a Post selection fails validation.
At the top level of the document, next to the operations, in any order. Every fragment defined must be used, or the server rejects the document as invalid.
Related: GraphQL vs REST, GraphQL mutations, GraphQL subscriptions, JavaScript async and fetch.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.