Docs
Launch GraphOS Studio

Fragments


The spec defines two types of fragments:

  • Named fragments, which enable you to reuse a set of across multiple or selection sets.
  • Inline fragments, which can group fields and apply type conditions or but are not reusable.

Both named and inline can be used as type conditions, which enables you to access fields of polymorphic types.

Read the guide on type conditions to learn more.

Named fragments

A named is defined in a .graphql file, just like an definition. A named fragment always has a name and a "parent type", that is, the type in the schema that it can be applied to. This fragment can be included in a selection set in an operation definition.

generates separate result types for named fragments, which means they are a great way of keeping UI components or utility functions independent of specific queries.

HeroDetailsFragment.graphql
fragment HeroDetails on Character {
name
appearsIn
}
HeroAndFriendsQuery.graphql
query HeroAndFriends {
hero {
name
...HeroDetails
friends {
...HeroDetails
}
}
}

Apollo iOS generates a type-safe model for the HeroDetails fragment that looks something like this (details are omitted to focus on the class structure):

HeroDetails.graphql.swift
struct HeroDetails: MySchema.SelectionSet, Fragment {
let name: String
let appearsIn: [Episode]
}

The result data models generated for the HeroAndFriendsQuery will include the fields from the HeroDetails fragment and are able to be converted into the HeroDetails fragment model.

HeroAndFriendsQuery.graphql.swift
class HeroAndFriendsQuery: GraphQLQuery {
struct Data: SelectionSet {
let hero: Hero
struct Hero: SelectionSet {
let name: String
let friends: [Friend]
let appearsIn: [Episode]
// Fragment Conversion Declaration
var fragments: Fragments
struct Fragments {
var heroDetails: HeroDetails { ... }
}
struct Friend: SelectionSet {
let name: String
let appearsIn: [Episode]
// Fragment Conversion Declaration
var fragments: Fragments
struct Fragments {
var heroDetails: HeroDetails { ... }
}
}
}
}
}

Fragment conversion

A result model that includes a fragment in it's definition will contain a Fragments struct that facilitates fragment conversion.

Both the Hero and the Friend models from the HeroAndFriendsQuery above have a Fragments struct and can be converted to the HeroDetails fragment.

let hero: HeroDetails = data.hero.fragments.heroDetails
let friends: [HeroDetails] = data.hero.friends.map { $0.fragments.heroDetails }

Fragment reuse

conversion allows you to reuse fragments as common models across different operations or multiple objects within the same operation.

One common pattern is to define a fragment for a child view, and include the fragment in a defined at a parent level. This way, the child view can easily be reused and only depends on the specific data it needs.

The HeroDetails fragment above is used for both the Hero and Friend models from the HeroAndFriendsQuery, but a hero can be displayed alongside their friends in your application by showing a list of views that each are configured with a HeroDetails fragment model.

HeroDetailsView.swift
struct HeroDetailsListView: View {
let data: HeroAndFriendsQuery.Data
var body: some View {
VStack {
HeroDetailsView(hero: data.hero.fragments.heroDetails)
for friend in data.hero.friends {
HeroDetailsView(hero: friend.fragments.heroDetails)
}
}
}
}
struct HeroDetailsView: View {
let hero: HeroDetails
var body: some View {
HStack {
Text(hero.name)
Text(hero.appearsIn.description)
}
}
}

You can add additional data to the HeroDetails fragment and display that data in the HeroDetailsView without affecting the parent view at all. Additionally, the HeroDetailsView can be used with other GraphQL operations that include the HeroDetails fragment.

Inline fragments

An inline fragment is a fragment that has no name. It is declared "inline" within another definition and cannot be reused. Inline fragments can be included in an operation definition, a named fragment definition, or nested inside another inline fragment. They are typically used to conditionally include fields in an operation using a type conditions or the @skip/@include directives.

Apollo iOS does not generate individual models for inline fragments, instead they affect the generated models for the operations or fragments containing them.

You can use inline fragments with type conditions to query for type-specific fields:

query HeroAndFriends($episode: Episode) {
hero(episode: $episode) {
name
... on Droid {
primaryFunction
}
}
}

And results from inline fragments with type conditions will be made available through specially generated as<Type> properties:

let name: String = data.hero.name
let primaryFunction: String = data.hero.asDroid?.primaryFunction

For more information about how to use inline fragments as type conditions, see the type conditions documentation.

Previous
Subscriptions
Next
Operation Arguments
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy

Company