Episode 25 menghubungkan frontend ke GraphQL dengan Apollo Client 3: setup client dan ApolloProvider, hook useQuery dengan polling dan refetch, useMutation dengan optimistic UI, manajemen cache InMemoryCache dan reactive variables, hingga pola integrasi React dengan custom hooks.

Semua kemampuan server GraphQL yang kalian bangun kini sampai pada bagian paling terlihat: frontend. Episode 25 menghubungkan aplikasi React kalian ke GraphQL dengan Apollo Client 3, library client paling populer di ekosistem. Kita akan membangun client dan provider, memakai hook useQuery dan useMutation, mengelola cache normalized, menangani local state dengan reactive variables, dan membahas pola integrasi React yang baik.
Install dengan npm install @apollo/client graphql, lalu konfigurasikan client dengan link HTTP dan cache:
import { ApolloClient, InMemoryCache, createHttpLink } from "@apollo/client";
const client = new ApolloClient({
link: createHttpLink({ uri: "http://localhost:4000" }),
cache: new InMemoryCache(),
});import { ApolloProvider } from "@apollo/client";
function App() {
return (
<ApolloProvider client={client}>
<HomePage />
</ApolloProvider>
);
}const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
username
}
}
`;
function Profile({ userId }) {
const { data, loading, error } = useQuery(GET_USER, {
variables: { id: userId },
});
if (loading) return <p>Memuat...</p>;
if (error) return <p>Terjadi kesalahan: {error.message}</p>;
return <h1>{data.user.username}</h1>;
}function Dashboard() {
const { data, refetch } = useQuery(GET_STATS, { pollInterval: 5000 });
return (
<div>
<Stats data={data} />
<button onClick={() => refetch()}>Segarkan</button>
</div>
);
}const ADD_COMMENT = gql`
mutation AddComment($postId: ID!, $body: String!) {
addComment(postId: $postId, body: $body) {
id
}
}
`;
function CommentBox({ postId }) {
const [addComment, { error }] = useMutation(ADD_COMMENT, {
optimisticResponse: {
addComment: { id: "optimistic-1", body: "Sedang dikirim...", __typename: "Comment" },
},
});
return (
<form onSubmit={(e) => { e.preventDefault(); addComment({ variables: { postId, body: formBody } }); }}>
{error && <p>{error.message}</p>}
</form>
);
}const [login, { loading }] = useMutation(LOGIN, {
onCompleted: (data) => {
localStorage.setItem("token", data.login.token);
navigate("/dashboard");
},
});const cached = client.cache.readQuery({ query: GET_USER, variables: { id: "1" } });
client.cache.writeQuery({
query: GET_USER,
variables: { id: "1" },
data: { user: { ...cached.user, username: "nama-baru" } },
});Ini berguna untuk optimistic updates yang presisi dan sinkronisasi antar komponen.
export const cartItemsVar = makeVar([]);
export const addToCart = (product) => cartItemsVar([...cartItemsVar(), product]);Komponen yang memakai useReactiveVar(cartItemsVar) otomatis re-render saat nilainya berubah — tanpa perlu Redux untuk state lokal yang sederhana.
function useUser(userId) {
return useQuery(GET_USER, { variables: { id: userId } });
}Kombinasikan dengan error boundaries untuk menangani kegagalan render, dan gunakan komponen yang kecil dan terspesialisasi. Apollo Client mendukung React Suspense untuk data fetching dengan komponen <Suspense> — pola modern yang akan kalian pakai lagi di episode 27.
Inti yang harus dibawa pulang:
useQuery memberi loading, error, dan data; refetch dan polling untuk data segar.useMutation dengan optimistic response membuat UI terasa instan.Di episode 26 selanjutnya kalian akan mempelajari alternatif GraphQL client — URQL dengan sistem exchanges-nya, Relay dengan fragment colocation dan compiler, kombinasi React Query dan graphql-request, hingga perbandingan lengkap Apollo versus URQL versus Relay. Kalian bisa memilih client yang tepat sesuai kebutuhan!