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 and apply type conditions or but are not reusable.

Both named and inline can be used as type conditions, which enables you to access 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 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 , 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
}
}
}

generates a type-safe model for the HeroDetails 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 from the HeroDetails and are able to be converted into the HeroDetails 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 in it's definition will contain a Fragments struct that facilitates conversion.

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

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 or multiple objects within the same operation.

One common pattern is to define a 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 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 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 and display that data in the HeroDetailsView without affecting the parent view at all. Additionally, the HeroDetailsView can be used with other that include the HeroDetails .

Inline fragments

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

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

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

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

And results from inline 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 as type conditions, see the type conditions documentation.

Previous
Subscriptions
Next
Operation Arguments
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy

Company