The fragment-based Apollo Client
Tags: graphql, apollo, react, javascript
Published: 2022-03-15 23:59:59

---
title: The fragment-based Apollo Client
published: true
description: The days that I had a hard time maintaining codebases with Apollo GraphQL are behind me. It all changed when I adopted a single concept.
tags: graphql, apollo, react, javascript
cover_image: https://images.unsplash.com/photo-1603031532585-34192bc4489f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1770&q=80
---

The days that I had a hard time maintaining codebases with Apollo GraphQL are behind me. It all changed when I adopted a single concept.

Apollo Client (a.k.a. Apollo GraphQL) is a GraphQL client used for consuming GraphQL data in web and mobile apps. It has caching, tracks network status, and does a fair amount of heavy lifting so developers can focus on building the product.

As the app grows and becomes more complex, it can get hard to know where the data is coming from and what piece of UI needs that data. What can be done to solve this is colocating [components](https://www.w3schools.com/react/react_components.asp) and [fragments](https://graphql.org/learn/queries/#fragments).

## Declaring the fragment

Let's say that we have a component that it's responsible for displaying a card with information about a user:

```jsx
// notice the component name, it will be used in the fragment
export const UserCard = ({ user }) => {
  return (
    <div>
      <h1>{user.name}</h1>
      <div>
        <img src={user.profile_picture?.uri} />
      </div>
    </div>
  );
};

// attach a fragments object to your component, more on that later
UserCard.fragments = {
  // notice that this is the name of the GraphQL type, using camel-case
  // the fragment name follows this pattern to avoid conflicts: <Component Name>_<GraphQL Type>
  // so in this case, the fragment name is UserCard_User
  user: gql`
    fragment UserCard_User on User {
      name
      profile_picture {
        uri
      }
    }
  `,
};
```

## Using the fragment

Now, we want to use this card on a page that we're building:

```jsx
import { UserCard } from '../components/UserCard';

const QUERY = gql`
  query UserPage {
    user(id: 200) {
      id
      # spread the fragment here, so it's included in the query
      ...UserCard_User
    }
  }
  ${UserCard.fragments.user}
`;

const UserPage = () => {
  const { data } = useQuery(QUERY);

  return (
    <div>
      <h1>Some nice title</h1>
      {/* pass the user data to the component */}
      <UserCard user={data.user} />
    </div>
  );
};
```

And that's all! The data declared in the `UserCard`  will also be included in the query and the page just needs to forward it to the component.

## Updating the fragment
So, let's say that after a few weeks the Product Manager comes back and says:

"Hey, we discovered that it's important to see the user last name as well. Can you add it?"

Sure thing! That's what we have to do:

```jsx
export const UserCard = ({ user }) => {
  return (
    <div>
      {/* add the last name in the UI */}
      <h1>
        {user.name} {user.last_name}
      </h1>
      <div>
        <img src={user.profile_picture?.uri} />
      </div>
    </div>
  );
};

UserCard.fragments = {
  user: gql`
    fragment UserCard_User on User {
      name
      # add the "last name" to the fragment
      last_name
      profile_picture {
        uri
      }
    }
  `,
};
```

So with just two lines of code, all the places that are using this card will be updated and have the right data. No more updating each query and passing down props. :rocket:

## Bonus: TypeScript

It gets even better with TypeScript, as when the types are generated, they're also colocated with the component:

```jsx
import { UserCard_User } from './__generated__/UserCard_User';

type Props = {
  user: UserCard_User;
};

export const UserCard = ({ user }: Props) => {
  return (
    <div>
      {/* add the last name in the UI */}
      <h1>
        {user.name} {user.last_name}
      </h1>
      <div>
        <img src={user.profile_picture?.uri} />
      </div>
    </div>
  );
};

UserCard.fragments = {
  user: gql`
    fragment UserCard_User on User {
      name
      # add the "last name" to the fragment
      last_name
      profile_picture {
        uri
      }
    }
  `,
};
```

### Thanks for reading!

What are your thoughts on using Apollo with fragments? How would you change it?

Let's keep in touch! Here's my [Twitter](https://twitter.com/julioxavierr).

### References
https://www.apollographql.com/docs/react/data/fragments/
https://relay.dev/docs/guided-tour/rendering/fragments
https://kentcdodds.com/blog/colocation