WJH
Posted on June 29, 2021
So I designed a schema for a common feature,
basically frontend needs to display two things:
- Summary of items
- The items
Suppose the page is about showing a list of
animals, and we want to show them the summary of
each type of animals.
FILTERS
[ ] Mammal (200)
[x] Birds (110)
[ ] Fish (200)
ITEMS
- Eagle
- Pigeon
- Stork
- ...
Initial Design
Initially, the schema I designed is as follows:
query {
displayAnimals(animalTypes: [AnimalType!]!): DisplayAnimalsResult!
}
enum AnimalType {
MAMMAL
BIRD
FISH
}
type DisplayAnimalsResult {
summary: DisplayAnimalsResultSummary!
animals: FilteredAnimals!
}
type DisplayAnimalsResultSummary {
mammal: Int!
bird: Int!
fish: Int!
}
type FilteredAnimals {
totalCount: Int!
paginate(pagingOptions: PagingOptions!): [Animal!]!
}
type PagingOptions {
currentPage: Int!
itemsPerPage: Int!
}
type Animal {
name: String!
}
And the frontend query:
query DisplayAnimal(
$animalTypes: [AnimalType!]!
$pagingOptions: PagingOptions!
) {
displayAnimals(animalTypes: $animalTypes) {
summary {
mammal
bird
fish
}
animals {
totalCount
paginate(pagingOptions: $pagingOptions) {
name
}
}
}
}
The Problem
- The summary is hardcorded. If frontend needed a new kind of summary, the schema has to change.
- The
summary
property feels like a boilerplate to implement.
A Better Design
After seeing this pattern over and over and getting
frustrated, I suddenly realised that the summary
property is actually not needed!
Let's see the new schema (note that DisplayAnimalsResult
and DisplayAnimalsResultSummary
are gone):
query {
displayAnimals(animalTypes: [AnimalType!]!): FilteredAnimals!
}
enum AnimalType {
MAMMAL
BIRD
FISH
}
type FilteredAnimals {
totalCount: Int!
paginate(pagingOptions: PagingOptions!): [Animal!]!
}
type PagingOptions {
currentPage: Int!
itemsPerPage: Int!
}
type Animal {
name: String!
}
And the frontend query (here's the magic, using
GraphQL Property Alias):
query DisplayAnimal(
$animalTypes: [AnimalType!]!
$pagingOptions: PagingOptions!
) {
mammal: displayAnimals(animalTypes: [MAMMAL]) {
totalCount
}
bird: displayAnimals(animalTypes: [BIRD]) {
totalCount
}
fish: displayAnimals(animalTypes: [FISH]) {
totalCount
}
displayAnimals(animalTypes: $animalTypes) {
animals {
totalCount
paginate(pagingOptions: $pagingOptions) {
name
}
}
}
}
How is this better?
- No need to implement
summary
resolver on backend, leading to lesser code. - The summary is no longer hardcoded, e.g. you can query total count of birds and fishes.
- Smaller schema, less noise.
Conclusion
GraphQL Alias is a powerful feature, thus remember to incorporate it when designing the schema.
P/S
Actually I wrote this for my workplace team. I decided to post it here because maybe others might find it helpful.
Posted on June 29, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.