Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
21 Sep 2025 · 5 min read ·Article 83 / 125
Go

83 Using Apollo Client in the Frontend

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

83 Using Apollo Client in the Frontend: A Comprehensive Guide to GraphQL Integration

GraphQL is becoming increasingly popular as a modern data-fetching solution for frontend applications. Unlike REST APIs, which require many endpoints, GraphQL lets us fetch data in a more flexible and efficient way. In the frontend world, Apollo Client is one of the de-facto libraries for connecting a React application (or other modern frameworks) to a GraphQL API. In this article, I will take a practical look at how to use Apollo Client in the frontend: from setup all the way to implementing queries and mutations, complete with code examples, simulations, and a flow diagram.


Why Choose Apollo Client?

As an engineer who has wrestled with fetch, AJAX, and REST APIs, I felt a huge difference when I started using Apollo Client:

  • Flexible Data Fetching: We can specify exactly what data the frontend needs, without over-fetching.
  • Automatic Caching: Data state is automatically synchronized and kept efficient through advanced caching.
  • Centralized Error Handling: Apollo provides clear, structured error handling.
  • Real-time Support: Subscriptions are built in!
  • Integration with React Hooks: A more idiomatic and modern development experience.

Diagram of the Apollo Client Workflow

To understand the workflow, here is the data-fetching flow when using Apollo Client in a frontend application:

MERMAID
flowchart TD
    A[User Action on UI] --> B[React Component Trigger Query/Mutation]
    B --> C[useQuery/useMutation Hook]
    C --> D[Apollo Client]
    D --> E[GraphQL Server]
    E --> F[Response Data]
    F --> G[Apollo Cache Update]
    G --> H[Component Rendered with Data]

Getting Started: Installation and Configuration

In this example, I will use React as the frontend foundation.

1. Installing the Library

bash
1npm install @apollo/client graphql

2. Configuring ApolloClient

In a React application, setup is usually done in the App.js file or in the entry file.

jsx
1// src/apolloClient.js
2import { ApolloClient, InMemoryCache } from "@apollo/client";
3
4const client = new ApolloClient({
5  uri: "https://api.example.com/graphql",  // Replace with your GraphQL endpoint
6  cache: new InMemoryCache(),
7});
8
9export default client;

Then, wire up the ApolloProvider at the root of the application:

jsx
 1// src/index.js
 2import React from "react";
 3import ReactDOM from "react-dom";
 4import { ApolloProvider } from "@apollo/client";
 5import client from "./apolloClient";
 6import App from "./App";
 7
 8ReactDOM.render(
 9  <ApolloProvider client={client}>
10    <App />
11  </ApolloProvider>,
12  document.getElementById("root")
13);

Querying Data with Apollo Client

Suppose we have the following GraphQL query:

graphql
1query GetUsers {
2  users {
3    id
4    name
5    email
6  }
7}

Let’s implement it in a React component:

jsx
 1import { gql, useQuery } from "@apollo/client";
 2
 3const GET_USERS = gql`
 4  query GetUsers {
 5    users {
 6      id
 7      name
 8      email
 9    }
10  }
11`;
12
13function UserList() {
14  const { loading, error, data } = useQuery(GET_USERS);
15
16  if (loading) return <p>Loading...</p>;
17  if (error) return <p>Error: {error.message}</p>;
18
19  return (
20    <ul>
21      {data.users.map(user => (
22        <li key={user.id}>
23          {user.name} ({user.email})
24        </li>
25      ))}
26    </ul>
27  );
28}

Sample Output

idnameemail
1Agungagung@domain.com
2Wulanwulan@domain.com

The component will auto-update whenever the cache changes, for example after a mutation.


Performing a Mutation: Adding Data

Suppose we have this mutation schema:

graphql
1mutation AddUser($name: String!, $email: String!) {
2  addUser(name: $name, email: $email) {
3    id
4    name
5    email
6  }
7}

Integrating it with React:

jsx
 1import { gql, useMutation } from "@apollo/client";
 2import { useState } from "react";
 3
 4const ADD_USER = gql`
 5  mutation AddUser($name: String!, $email: String!) {
 6    addUser(name: $name, email: $email) {
 7      id
 8      name
 9      email
10    }
11  }
12`;
13
14function AddUserForm() {
15  const [name, setName] = useState("");
16  const [email, setEmail] = useState("");
17  const [addUser, { loading, error }] = useMutation(ADD_USER, {
18    // Update the cache after the mutation succeeds
19    update(cache, { data: { addUser } }) {
20      cache.modify({
21        fields: {
22          users(existingUsers = []) {
23            const newUserRef = cache.writeFragment({
24              data: addUser,
25              fragment: gql`
26                fragment NewUser on User {
27                  id
28                  name
29                  email
30                }
31              `,
32            });
33            return [...existingUsers, newUserRef];
34          },
35        },
36      });
37    },
38  });
39
40  const handleSubmit = e => {
41    e.preventDefault();
42    addUser({ variables: { name, email } });
43  };
44
45  return (
46    <form onSubmit={handleSubmit}>
47      <input value={name} onChange={e => setName(e.target.value)} placeholder="Name" />
48      <input value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" />
49      <button type="submit" disabled={loading}>Add User</button>
50      {error && <p>Error: {error.message}</p>}
51    </form>
52  );
53}

Scenario: Error Handling & Loading

Apollo helps developers handle loading and error states in an idiomatic way.

jsx
1const { loading, error, data } = useQuery(GET_USERS);
2
3if (loading) return <Spinner />;
4if (error)   return <Alert>{error.message}</Alert>;

Comparison Table: Apollo Client vs Fetch API

FeatureApollo ClientFetch API
Automatic CacheYesNo
Query BuilderYes (GQL)Manual
RealtimeYes (Subscription)Not native
PaginationEasy (Relay/Cache)Manual
Error HandlingStructured (Hooks)Manual

Brief Case Study: Realtime Subscription

Suppose we want to listen to data in real time:

jsx
 1import { gql, useSubscription } from "@apollo/client";
 2
 3const USER_ADDED = gql`
 4  subscription OnUserAdded {
 5    userAdded {
 6      id
 7      name
 8      email
 9    }
10  }
11`;
12
13function UserAddedListener() {
14  const { data, loading } = useSubscription(USER_ADDED);
15
16  if (loading) return null;
17  return <p>New user: {data.userAdded.name}</p>;
18}

Conclusion

Integrating Apollo Client into the frontend makes both productivity and data management structure far better. With its ergonomic API, automatic caching, integrated error handling, and real-time support, Apollo Client meets the needs of complex and demanding modern applications. If you are working with GraphQL, Apollo Client is the best investment for your frontend codebase.


Danger
Note: For a deeper implementation, study Advanced Apollo features such as fragments, pagination, optimistic UI, or local schema state for powerful data orchestration in the frontend. Happy exploring!

References:

Related Articles

💬 Comments