Managing Cache with Apollo in React JS

Introduction

Apollo Client uses an in-memory cache to store the results of your GraphQL queries. This allows Apollo to automatically update your UI with cached data and send fewer requests to your server. In this tutorial, we will explore how to manage cache with Apollo in a React app.

Step 1: Setting Up Apollo Client

Before managing cache, ensure that you have set up Apollo Client in your React app. If you haven’t done so already, follow the steps below:

Install Apollo Client and GraphQL:


  npm install @apollo/client graphql
      

Create an Apollo Client instance:


  import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
  
  const client = new ApolloClient({
    uri: 'http://localhost:4000/',  // Replace with your GraphQL API endpoint
    cache: new InMemoryCache(),  // This is where caching happens
  });
  
  export default client;
      

Wrap your app with ApolloProvider in your main entry file:


  import { ApolloProvider } from '@apollo/client';
  import client from './apolloClient';
  import App from './App';
  
  ReactDOM.render(
    
      
    ,
    document.getElementById('root')
  );
      

Step 2: Using Cache in Apollo Client

Apollo Client uses an in-memory cache to store query results. By default, it caches the results of your queries so that subsequent requests for the same data are served from the cache rather than making a network request.

Example: Query and Caching Data

Let's fetch a list of users and take advantage of caching:


  import React from 'react';
  import { useQuery, gql } from '@apollo/client';
  
  // Define the query to fetch users
  const GET_USERS = gql`
    query GetUsers {
      users {
        id
        name
      }
    }
  `;
  
  const UsersList = () => {
    const { loading, error, data } = useQuery(GET_USERS);
  
    if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; return (
    {data.users.map((user) => (
  • {user.name}
  • ))}
); }; export default UsersList;

When you first make this query, Apollo Client fetches data from the server and stores it in its cache. The next time you make the same query, Apollo will serve the data from the cache without making a network request.

Step 3: Customizing Cache Behavior

Apollo Client allows you to customize how the cache works using options such as fetchPolicy and nextFetchPolicy to control when the cache should be read or updated.

Using fetchPolicy

The fetchPolicy option determines how Apollo Client fetches data for a query. By default, it uses 'cache-first', meaning it will try to fetch data from the cache first and only make a network request if the data isn’t in the cache.


  const { loading, error, data } = useQuery(GET_USERS, {
    fetchPolicy: 'network-only',  // Force a network request every time
  });
      

Cache-first Policy

The default fetch policy is cache-first. This means Apollo Client will first check the cache for existing data and only request data from the server if it's not available in the cache.

Network-only Policy

The network-only fetch policy forces Apollo Client to always fetch data from the network and never use the cache.

Cache-and-network Policy

The cache-and-network policy returns data from the cache if available but always triggers a network request to get updated data:


  const { loading, error, data } = useQuery(GET_USERS, {
    fetchPolicy: 'cache-and-network',
  });
      

Step 4: Manually Updating the Cache

In some cases, you may need to manually update the cache after performing a mutation (e.g., adding a new user). You can do this by using Apollo Client's cache.writeQuery and cache.writeFragment methods.

Example: Updating Cache after a Mutation

Let’s create a mutation that adds a new user and updates the cache to reflect the changes immediately:


  import React, { useState } from 'react';
  import { useMutation, gql } from '@apollo/client';
  import { GET_USERS } from './UsersList';
  
  const ADD_USER = gql`
    mutation AddUser($name: String!) {
      addUser(name: $name) {
        id
        name
      }
    }
  `;
  
  const AddUserForm = () => {
    const [name, setName] = useState('');
    const [addUser] = useMutation(ADD_USER, {
      update(cache, { data: { addUser } }) {
        // Read the data from the cache
        const { users } = cache.readQuery({ query: GET_USERS });
  
        // Update the cache by adding the new user
        cache.writeQuery({
          query: GET_USERS,
          data: { users: users.concat([addUser]) },
        });
      }
    });
  
    const handleSubmit = async (e) => {
      e.preventDefault();
      try {
        await addUser({ variables: { name } });
        setName('');
      } catch (error) {
        console.error("Error adding user:", error);
      }
    };
  
    return (
      
setName(e.target.value)} placeholder="Enter user name" />
); }; export default AddUserForm;

In the code above:

  • update: The update function allows us to modify the cache after the mutation is completed. We manually update the cache by reading the current data with cache.readQuery and then writing the updated data with cache.writeQuery.

Step 5: Cache Eviction and Resetting

Sometimes, you may want to clear or reset the cache. Apollo Client provides methods to reset the cache when needed.

Evicting a Specific Cache

You can evict a specific cache entry using cache.evict:


  client.cache.evict({ id: 'User:1' });  // Evict the user with ID 1
  client.cache.gc();  // Garbage collect to remove the evicted cache entry
      

Resetting the Entire Cache

If you need to reset the entire cache, you can use the client.resetStore() method:


  client.resetStore();  // Resets the entire cache and refetches active queries
      

Step 6: Running Your Application

After setting up cache management, run your React app to test cache behavior:


  npm start
      

Your application should now be using Apollo Client’s cache to store and update data efficiently.

Conclusion

In this tutorial, we learned how to:

  • Use Apollo Client's cache to store query results.
  • Control fetch policies to manage cache behavior.
  • Manually update the cache after a mutation.
  • Evict and reset the cache when needed.

By understanding and managing Apollo Client’s cache, you can significantly improve the performance of your React applications by reducing network requests and ensuring that your UI is always in sync with the latest data.





Advertisement