Fragments

Fragment is to share the fields in our query or mutation. Concept of fragments happening on the client-side

To create a fragment, we use the following syntax:

fragment sharedFields on User {
  username
  friends {
    name
  }
}

And then we can reuse it across our query

query QueryUser { 
  users { 
	...sharedFields
  }  
  
  findAllUserByUsername(username: $username) { 
    ...sharedFields
  } 
}

fragment sharedFields on User {
  username
  friends {
    name
  }
}

Inline-fragments

To create inline-fragments, we use the same syntax

query QueryUser { 
  users { 
	... on User {
		username
		friends { 
			name	
		}
	}
  }  
}

This will automatically filter out by type of the object as well.

Conditional fields using fragments.

Consider that now we have an interface and 2 different types:

interface IUser {
  username: String
  password: String
}

type User implements IUser {
  username: String
  password: String
  friends: [Friend]
}

type Admin implements IUser { 
  username: String
  password: String
  permission: [String]
}

Our database now also returns differently:

var database = [
  {
    __typename: "User",
    username: "Test",
    password: "12345",
    friends: [
      {
        name: "Teddy"
      },
      {
        name: "Long"
      }
    ]
  },
  {
    __typename: "User",
    username: "Test2",
    password: "1234",
    friends: [
      {
        name: "Vu"
      },
    ]
  },
  {
    __typename: "Admin",
    username: "admin",
    password: "1234",
    permission: ["*"]
  }
];

Note: we use __typename here to declare the type of each object. This is necessary when dealing with 2 types in the same time.

Since the field is now different, we cannot use the following syntax to query anymore

query QueryUser($withFriends: Boolean! = false, $skipUsername: Boolean! = false) { 
  users { 
    username @skip(if: $skipUsername), 
    friends @include(if: $withFriends) {
      name
    }
  }  
} 

Because Admin doesn't have friends but have permissions. Therefore, we need to extract these fields into fragments:

query QueryUser($withFriends: Boolean! = false, $skipUsername: Boolean! = false) { 
  users { 
    username @skip(if: $skipUsername), 
    ... on User {
      friends @include(if: $withFriends) {
        name
      }
    }
    ... on Admin {
      permission
    }
  }  
} 

As a result:

{
    "data": {
        "users": [
            {
                "__typename": "User",
                "friends": [
                    {
                        "name": "Teddy"
                    },
                    {
                        "name": "Long"
                    }
                ]
            },
            {
                "__typename": "User",
                "friends": [
                    {
                        "name": "Vu"
                    }
                ]
            },
            {
                "__typename": "Admin",
                "permission": [
                    "*"
                ]
            }
        ]
    }
}