GRAPHQL FRONTEND STATE-MANAGEMENT DATA-FETCHING REACT JAVASCRIPT CLIENT-SIDE CACHING WEB-DEVELOPMENT API-CONSUMPTION APOLLO-CLIENT DEVELOPER-EXPERIENCE

Mengelola Data GraphQL di Frontend: Memilih dan Menggunakan Apollo Client untuk Aplikasi Modern

⏱️ 12 menit baca
👨‍💻

Mengelola Data GraphQL di Frontend: Memilih dan Menggunakan Apollo Client untuk Aplikasi Modern

Di era aplikasi web modern yang kompleks, mengelola data di sisi frontend bisa menjadi tantangan tersendiri. Kita perlu memikirkan bagaimana data diambil, disimpan, di-cache, di-update, dan ditampilkan secara efisien. Jika Anda sudah akrab dengan GraphQL sebagai arsitektur API yang kuat untuk backend, pertanyaan selanjutnya adalah: bagaimana cara terbaik untuk mengonsumsi API GraphQL ini di sisi frontend?

Meskipun Anda bisa saja menggunakan fetch() API bawaan browser untuk mengirim query dan mutation GraphQL, pendekatan ini akan membuat Anda harus mengurus banyak hal manual: manajemen loading state, error handling, caching, normalisasi data, hingga integrasi dengan framework UI Anda. Di sinilah peran GraphQL Client Libraries menjadi sangat krusial.

Dalam artikel ini, kita akan menyelami mengapa library client GraphQL sangat penting dan bagaimana salah satu yang paling populer, Apollo Client, dapat menyederhanakan seluruh proses pengelolaan data GraphQL di aplikasi frontend Anda. Kita akan fokus pada contoh praktis menggunakan React, namun konsepnya bisa diaplikasikan ke framework lain.

1. Pendahuluan: Mengapa Frontend Membutuhkan Bantuan untuk GraphQL?

Anda mungkin sudah tahu bahwa GraphQL memberikan fleksibilitas luar biasa di sisi server, memungkinkan klien untuk meminta data persis yang mereka butuhkan. Ini mengurangi over-fetching dan under-fetching, serta menyederhanakan pengembangan API. Namun, di sisi frontend, kompleksitas masih tetap ada:

Mengimplementasikan semua ini dari awal dengan fetch() bisa sangat melelahkan dan rawan bug. Inilah alasan utama keberadaan library seperti Apollo Client.

2. Mengenal Apollo Client: Otak di Balik Data GraphQL Anda

📌 Apollo Client adalah library manajemen state yang komprehensif untuk aplikasi JavaScript yang mengonsumsi API GraphQL. Ini bukan hanya sekadar pengganti fetch(), melainkan sebuah ekosistem lengkap yang dirancang untuk mempermudah seluruh siklus hidup data GraphQL di frontend Anda.

Beberapa fitur inti Apollo Client meliputi:

3. Mengapa Menggunakan GraphQL Client Library (Bukan fetch() Biasa)?

Mengapa Anda harus repot-repot menambahkan dependensi lain hanya untuk mengambil data? Berikut adalah beberapa alasan kuat:

💡 Analogi: Bayangkan fetch() seperti mengendarai mobil tanpa GPS, radio, AC, atau bahkan jok yang nyaman. Anda bisa sampai tujuan, tapi dengan banyak usaha dan ketidaknyamanan. Apollo Client adalah mobil mewah lengkap dengan semua fitur: GPS (caching), radio (subscriptions), AC (error handling), dan jok nyaman (developer experience) yang membuat perjalanan Anda jauh lebih mulus.

4. Memulai dengan Apollo Client di Aplikasi React

Mari kita lihat bagaimana Apollo Client diimplementasikan dalam aplikasi React.

Langkah 1: Instalasi

npm install @apollo/client graphql
# atau
yarn add @apollo/client graphql

Langkah 2: Konfigurasi Client

Buat instance Apollo Client dan hubungkan ke endpoint GraphQL Anda.

// src/apolloClient.js
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';

const client = new ApolloClient({
  uri: 'http://localhost:4000/graphql', // Ganti dengan endpoint GraphQL Anda
  cache: new InMemoryCache(),
});

export default client;

Langkah 3: Sediakan Client untuk Aplikasi Anda

Bungkus root aplikasi React Anda dengan ApolloProvider.

// src/App.js
import React from 'react';
import { ApolloProvider } from '@apollo/client';
import client from './apolloClient';
import PostsList from './components/PostsList'; // Akan kita buat nanti

function App() {
  return (
    <ApolloProvider client={client}>
      <div className="App">
        <h1>Blog Saya</h1>
        <PostsList />
      </div>
    </ApolloProvider>
  );
}

export default App;

Langkah 4: Mengambil Data dengan useQuery

Sekarang, di dalam komponen PostsList, kita bisa mengambil data menggunakan hook useQuery.

// src/components/PostsList.js
import React from 'react';
import { useQuery, gql } from '@apollo/client';

// Definisikan GraphQL Query Anda
const GET_POSTS = gql`
  query GetPosts {
    posts {
      id
      title
      content
      author {
        name
      }
    }
  }
`;

function PostsList() {
  const { loading, error, data } = useQuery(GET_POSTS);

  if (loading) return <p>Loading posts...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <div>
      <h2>Daftar Artikel</h2>
      {data.posts.map(post => (
        <div key={post.id} style={{ border: '1px solid #ccc', padding: '10px', margin: '10px 0' }}>
          <h3>{post.title}</h3>
          <p>{post.content.substring(0, 100)}...</p>
          <p>Oleh: {post.author.name}</p>
        </div>
      ))}
    </div>
  );
}

export default PostsList;

Poin Penting:

5. Mengirim Data dengan useMutation

Selain mengambil data, Anda juga perlu mengirim atau memodifikasi data. Ini dilakukan dengan GraphQL Mutations dan hook useMutation.

Misalnya, kita ingin menambahkan artikel baru.

// src/components/AddPostForm.js
import React, { useState } from 'react';
import { useMutation, gql } from '@apollo/client';

const ADD_POST = gql`
  mutation AddPost($title: String!, $content: String!, $authorId: ID!) {
    addPost(title: $title, content: $content, authorId: $authorId) {
      id
      title
      content
      author {
        name
      }
    }
  }
`;

// Kita juga perlu query untuk memperbarui daftar post setelah menambah post baru
// Ini bisa jadi GET_POSTS yang sama dari PostsList.js
const GET_POSTS = gql`
  query GetPosts {
    posts {
      id
      title
      content
      author {
        name
      }
    }
  }
`;

function AddPostForm() {
  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');
  const [authorId, setAuthorId] = useState(''); // Asumsi kita tahu ID author

  const [addPost, { loading, error }] = useMutation(ADD_POST, {
    // Strategi untuk memperbarui cache setelah mutasi
    update(cache, { data: { addPost } }) {
      // Baca cache yang ada untuk query GET_POSTS
      const existingPosts = cache.readQuery({ query: GET_POSTS });

      // Tulis ulang cache dengan post baru ditambahkan
      cache.writeQuery({
        query: GET_POSTS,
        data: { posts: [addPost, ...existingPosts.posts] },
      });
    },
    // Atau, lebih sederhana, bisa juga melakukan refetch query
    // refetchQueries: [{ query: GET_POSTS }],
  });

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      await addPost({ variables: { title, content, authorId } });
      setTitle('');
      setContent('');
      setAuthorId('');
      alert('Artikel berhasil ditambahkan!');
    } catch (err) {
      console.error(err);
    }
  };

  return (
    <form onSubmit={handleSubmit} style={{ border: '1px dashed #ccc', padding: '20px', margin: '20px 0' }}>
      <h2>Tambah Artikel Baru</h2>
      <div>
        <label>Judul:</label>
        <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} required />
      </div>
      <div>
        <label>Konten:</label>
        <textarea value={content} onChange={(e) => setContent(e.target.value)} required />
      </div>
      <div>
        <label>ID Penulis:</label>
        <input type="text" value={authorId} onChange={(e) => setAuthorId(e.target.value)} required />
      </div>
      <button type="submit" disabled={loading}>
        {loading ? 'Menambahkan...' : 'Tambah Artikel'}
      </button>
      {error && <p style={{ color: 'red' }}>Error: {error.message}</p>}
    </form>
  );
}

export default AddPostForm;

⚠️ Pentingnya update atau refetchQueries: Setelah melakukan mutasi, Anda seringkali perlu memperbarui UI. Apollo Client tidak secara otomatis tahu bagaimana mutasi Anda memengaruhi cache. Anda bisa:

  1. Menggunakan fungsi update untuk memanipulasi cache secara langsung (lebih performant).
  2. Menggunakan refetchQueries untuk mengambil ulang query yang relevan setelah mutasi (lebih mudah, tapi bisa kurang performant).

6. Tips dan Praktik Terbaik dengan Apollo Client

Berikut adalah beberapa tips untuk memaksimalkan penggunaan Apollo Client:

🎯 Tujuan Akhir: Dengan Apollo Client, Anda dapat membangun aplikasi frontend yang cepat, responsif, dan mudah dipelihara, dengan fokus pada logika bisnis dan UI, bukan pada boilerplate pengelolaan data.

Kesimpulan

Mengelola data di aplikasi frontend modern yang mengonsumsi GraphQL API bisa menjadi kompleks. Namun, dengan bantuan library seperti Apollo Client, proses ini dapat disederhanakan secara drastis. Dari caching otomatis yang cerdas, manajemen loading dan error state yang intuitif, hingga dukungan untuk real-time subscriptions dan optimistic UI, Apollo Client menyediakan semua yang Anda butuhkan untuk pengalaman developer yang luar biasa dan aplikasi yang performant.

Dengan memahami dan mengimplementasikan Apollo Client, Anda tidak hanya menghemat waktu pengembangan, tetapi juga membangun fondasi yang kuat untuk aplikasi yang skalabel dan mudah dipelihara. Jadi, jika Anda sedang membangun atau berencana membangun aplikasi dengan GraphQL, Apollo Client adalah teman terbaik Anda di sisi frontend.

🔗 Baca Juga