close icon
daily.dev platform

Discover more from daily.dev

Personalized news feed, dev communities and search, much better than what’s out there. Maybe ;)

Start reading - Free forever
Start reading - Free forever
Continue reading >

React Apollo Basics for Beginners

React Apollo Basics for Beginners
Author
Nimrod Kramer
Related tags on daily.dev
toc
Table of contents
arrow-down

🎯

Learn React Apollo basics for beginners, including setting up Apollo Client, fetching data with queries, using Apollo hooks, handling loading states and errors efficiently, and optimizing app performance. Explore GraphQL benefits and Apollo features.

React Apollo bridges your React app and a GraphQL server, simplifying data retrieval and management. This guide equips beginners with the essentials, including:

  • Setting up Apollo Client with a GraphQL server
  • Fetching data using queries and updating data with mutations
  • Using React Apollo hooks for seamless integration
  • Automatically updating data in your app post-mutations
  • Handling loading states and errors efficiently
  • Optimizing app performance and conducting tests

Whether you're new to React Apollo or seeking to solidify your understanding, this guide provides a comprehensive overview, practical examples, and tips for effective usage.

What is GraphQL?

GraphQL is a special way to ask for data from websites or apps. It's like going to a restaurant and being able to order exactly what you want, how you want it, instead of getting a fixed menu. Here's why it's cool:

  • You get just what you ask for: You can tell the server exactly what data you need, and it sends back just that. No more, no less. This means your app can run faster and smoother.
  • It's clear and organized: GraphQL has a set way of showing what data is available. This is like having a menu that tells you exactly what ingredients are in each dish.
  • Easy to get lots of related data: It's simple to ask for related data in one go. Imagine getting your main dish, sides, and dessert all served together.
  • Saves data: Since you only ask for what you need, it doesn't use up unnecessary data. This is great when you're on a limited data plan.
  • No more version headaches: When new features are added, your old requests still work. So, your app won't break when there are updates.

In short, GraphQL makes it easier to get exactly what you need from a server without any fuss.

Introduction to Apollo

Apollo Client is a tool that helps your web or mobile app talk to a GraphQL server. Think of it as a translator that knows exactly how to ask for what you need. Here's what makes it special:

  • Straightforward asking: You can write your data requests right where you're going to use them. This keeps things tidy and easy to manage.
  • Smart memory use: Apollo remembers what you've asked for before, so it doesn't waste time asking again. This means your app can run faster.
  • Tools to help you out: Apollo comes with tools that let you see what's happening behind the scenes. This can help you fix issues and understand your app better.
  • Automatic updates: When the data changes, Apollo automatically updates your app. You don't have to do anything.
  • Quick changes: Apollo can make your app look like it's updated instantly, even before the server has responded. This makes your app feel faster.
  • Add-ons: Apollo supports extra features for things like saving data, handling errors, and improving performance.

In a nutshell, Apollo makes it easier and faster to get and use data in your app, thanks to its smart features.

Setting Up Your Environment

Prerequisites

Before diving into React Apollo, make sure you're familiar with:

  • Basic HTML
  • CSS
  • JavaScript (focus on ES6 features)
  • React fundamentals (like how components, props, state, and hooks work)

You should also have these tools ready:

  • Node.js (version 14 or newer)
  • A text editor (VS Code is a good choice: VS Code)
  • git (this is optional)
  • A terminal (like Terminal on Mac or iTerm)

Setting Up a React Project

There are a couple of ways to start a new React project.

Local Setup

To set up a React app on your computer, open your terminal and type:

npx create-react-app my-app
cd my-app
npm start

This command creates a new folder called my-app with your React project and opens it.

CodeSandbox

If you want to start quickly without installing anything, try CodeSandbox. Just choose the React template to get going.

Installing Apollo Client

Apollo Client

Next, you need to add Apollo Client to your project. Install it by running:

npm install @apollo/client graphql

@apollo/client is what you use to set up Apollo Client in your React app.

graphql is needed to work with GraphQL queries.

After installing these, you're ready to set up Apollo Client with React, which we'll talk about in the following parts.

Integrating Apollo Client with React

Initializing Apollo Client

To start working with Apollo Client in your React app, you first need to set it up. Think of Apollo Client as the middleman that helps your app talk to the GraphQL server.

Here's a simple way to set up Apollo Client:

import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://api.graphql.example/graphql',
  cache: new InMemoryCache()
});

In this setup, we tell Apollo Client where to find the GraphQL server (uri) and how to store the data it gets (cache). You can also add more settings if needed, like setting up headers for secure connections.

Once Apollo Client is ready, you can start asking for data (queries) or sending data (mutations) to your server.

The ApolloProvider Component

To make Apollo Client work with your React app, you need to link them together. This is where ApolloProvider comes in.

Just wrap your whole React app with ApolloProvider and give it your client:

import { ApolloProvider } from '@apollo/client';

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root')
);

By doing this, every component in your app can talk to Apollo Client. This means any part of your app can now easily ask for or change data using hooks like useQuery and useMutation.

So, ApolloProvider is basically the piece that connects your React app with Apollo Client, making it easy for your components to get and use data.

Fetching Data with Apollo Client

Writing Your First Query

To get data in your React component using Apollo Client, you'll want to use the useQuery hook. Here's a simple example:

import { useQuery, gql } from '@apollo/client';

const GET_TODOS = gql`
  query GetTodos {
    todos {
      id 
      text
    }
  }
`;

function Todos() {
  const { loading, error, data } = useQuery(GET_TODOS);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error!</p>;

  return data.todos.map((todo) => (
    <p key={todo.id}>{todo.text}</p>
  ));
}

First, we make our GraphQL query with the gql tag. This query asks for a list of todos.

Then, in our component, we run the query by giving it to useQuery. This gives us an object with loading, error, and data which we use to manage the state.

When it's loading, we show a message. If there's an error, we show an error message. And when we get the data, we display the todos.

This way, useQuery lets us clearly state what data we need and lets us update our UI based on the data's state.

Handling Query Results

The useQuery hook gives us a result object with three key states:

  • loading - Tells us if the query is still going
  • error - Any errors from the query
  • data - The data we got back from the query

Here's how to handle each state:

Loading State

Display a loading message at the start:

if (loading) return <p>Loading...</p>;

Error State

Show a message if there's an error:

if (error) return <p>Error!</p>;

Data State

Then, use the data to render your UI:

return data.todos.map((todo) => (
  <p key={todo.id}>{todo.text}</p>
));

Handling these states lets you accurately show what's happening in your UI.

For an even better user experience, you can use onCompleted and onError options to run code when a query finishes or if there's an error. This can be handy for actions like moving the user to the top of a list when new data comes in.

In short, using these query states wisely helps make your app's interface smooth and user-friendly.

Mutations and Local State Management

Performing Mutations

Mutations let you change data on the server. Think of them like sending a text message to the server saying, "Hey, update this information for me, please." With Apollo Client, you use something called useMutation to do this. Here's a simple way to add a new to-do item to a list:

import { useMutation, gql } from '@apollo/client';

const ADD_TODO = gql`
  mutation AddTodo($text: String!) {
    addTodo(text: $text) {
      id
      text
    }
  }
`;

function AddTodo() {
  const [addTodo] = useMutation(ADD_TODO);

  const handleSubmit = (event) => {
    event.preventDefault();
    const formData = new FormData(event.target);
    const text = formData.get('text');
    
    addTodo({ variables: { text } });
  }

  return (
    <form onSubmit={handleSubmit}>
      <input name="text" />
      <button type="submit">Add Todo</button> 
    </form>
  );
}

In this setup:

  • You write down what you want to change using gql
  • Use useMutation to get ready to make the change
  • When you submit, you tell the server what to update
  • If needed, the server will update the info on your screen too

You can also show a loading message, deal with any errors, and even make updates look instant to improve how it feels to use your app.

Managing Local State

Sometimes, you need to keep track of info that's just for your app and not on the server. Apollo has some neat ways to do this:

Query Result Object

For simple things, you can use the result of a query as a kind of temporary storage.

Like if you're filtering a list of to-dos:

function Todos() {
  const [filter, setFilter] = useState('all');
  
  const { data } = useQuery(GET_TODOS, {
    variables: {
      filter  
    }
  });

  return (
    <>
      <button onClick={() => setFilter('done')}>
        Done
      </button>
      {data.todos.map(...)}
    </>
  );
}

Here, the filter is just for your app, but it helps decide what to-dos to show.

Reactive Variables

For more complicated stuff, Apollo has something called makeVar and reactive variables.

const filterVar = makeVar('all');

function Todos() {
  const filter = filterVar();

  const { data } = useQuery(GET_TODOS, {
    variables: {
      filter: filterVar()
    }
  });
  
  // ...
}

This makes a special kind of variable that updates your list automatically when it changes.

So, Apollo gives you tools like query variables and reactive variables to help you manage both server data and your app's own info.

sbb-itb-bfaad5b

Advanced Topics

Let's dive into some more advanced stuff with Apollo that can really make your app stand out.

Apollo Client Caching

Apollo Client has a smart way of storing data called normalized caching. This means Apollo keeps track of your data in a smart way that understands how different pieces are connected.

For instance, if you have a list of tasks and info about who created them, Apollo stores the tasks and creators separately to avoid repeating the same info. Then, it can easily connect them when needed.

You can tell Apollo how to handle your data with cache directives:

const GET_TODOS = gql`
  query GetTodos {
    todos @client {
      id  
      text
    }
  }
`;

The @client directive here means "keep this data on the user's device".

Other directives like @export help manage how data pieces relate to each other.

You can also directly manage the cache with the read and write API:

client.readQuery({ query: GET_TODOS });

client.writeQuery({
  query: GET_TODOS,
  data: {
    todos: [
      // ... new tasks
    ]
  }
});

This gives you full control for things like making your app feel faster by predicting updates.

In short, Apollo's caching helps your app run smoother, look more consistent, and lets you do more complex stuff easily.

Real-time Updates with Subscriptions

Apollo Client also supports GraphQL subscriptions for live updates. This uses a technology called WebSocket to stay connected to the server.

To use it:

const NEW_TODOS = gql`
  subscription NewTodos {
    newTodo {
      id
      text
    }
  }
`;

const { data } = useSubscription(NEW_TODOS);

This means when there's a new task, Apollo automatically updates your app!

Subscriptions keep a constant connection, so your app can instantly show changes without waiting. This is great for things like live news feeds or getting instant notifications.

Best Practices

When working with React Apollo, here are some smart moves to make your apps work better and faster:

Performance

  • Batch your queries: This means sending a bunch of data requests together instead of one by one. It's like making one trip to the grocery store instead of going back and forth for each item.
  • Remember data you've already gotten: Apollo can do this for you. It stops your app from asking for the same thing over and over, saving time.
  • Keep some data just on your device: Using things like @client tells Apollo to not bother the server for this data, making things quicker.
  • Get data ready before you need it: This can make your app seem faster because it has the data ready when you go to look at it.
  • Don't ask for too much at once: Start with a little, then get more as needed. This keeps your app from getting bogged down right at the start.
  • Check on slow spots: If something's taking too long, find out why and see if you can make it faster or do it later.

Caching

  • Organize your data well: Make sure Apollo knows how your data fits together. This helps it use the data more efficiently.

  • Tell Apollo exactly how to handle your data: You can set rules for how to store, update, or get rid of data.

  • Clean up old data: If something changes, make sure Apollo knows to update or remove the old data.

Error Handling

  • Plan for mistakes: Decide how to deal with errors in one place, so you don't have to worry everywhere.

  • Protect your app from crashing: Use safeguards to keep one error from breaking everything.

  • Know the difference between network and GraphQL errors: This helps you figure out what went wrong more easily.

  • Try again if needed: If something doesn't work at first, have a plan to try again a little later.

Dependencies

  • Only use what you need: Don't bog down your app with extra stuff. Pick and choose the parts of Apollo you really need.
  • Use hooks: They're simpler and can help keep your app running smoothly.

By following these tips, you can make your app run smoother and handle problems better. It's all about being smart with how you use Apollo and React together.

Building a Sample Application

Let's create a simple todo list app to see React Apollo in action. We'll go through these steps:

  • Getting a GraphQL server ready
  • Setting up our React project
  • Linking our app to the server
  • Showing the todo list
  • Adding features to create, update, and delete todos

This will show us the whole process of using React Apollo, from the server side to the client side.

Setting Up a GraphQL Server

GraphQL

First, we need a server that our React app can talk to. We'll use Apollo Server and Prisma to set one up quickly.

  • Install the necessary packages:
npm install apollo-server graphql prisma
  • Get Apollo Server running:
const { ApolloServer } = require('apollo-server');

const server = new ApolloServer({
  typeDefs, 
  resolvers,
});

server.listen().then(() => {
  console.log(`Server ready at http://localhost:4000`);
});
  • Prepare your Prisma schema and generate the Prisma Client
  • Create resolvers to connect to your database

Now, our GraphQL server is up and running, ready to manage todo items!

Creating the React Project

React

Next, we'll set up our React app using Create React App:

npx create-react-app my-app
cd my-app

After that, we'll add Apollo Client to our project and set it up:

// Add necessary packages
npm install @apollo/client graphql

// Set up Apollo Client
const client = new ApolloClient({
  uri: 'http://localhost:4000',
  cache: new InMemoryCache() 
});

Connecting Apollo Client

To link Apollo Client with our app, we use ApolloProvider to wrap our app:

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>, 
  document.getElementById('root')
);

This connects our React app with Apollo Client.

Fetching Todos

Now, inside our app, we can get our todo list:

const GET_TODOS = gql`
  query GetTodos {
    todos {
      id 
      text
    }
  }
`;

function Todos() {
  const { data } = useQuery(GET_TODOS)
  
  return (
    <ul>
      {data.todos.map(todo => (
        <li key={todo.id}>{todo.text}</li>  
      ))}
    </ul>
  )
}

We use useQuery to ask for and show the todos.

Adding Mutations

Let's add a feature to let users create new todos:

const ADD_TODO = gql`
  mutation AddTodo($text: String!) {
    addTodo(text: $text) {
      id
      text 
    }
  }  
`;

function AddTodo() {
  const [addTodo] = useMutation(ADD_TODO);
  
  return (
    <form 
      onSubmit={e => {
        e.preventDefault();
        addTodo({
          variables: {
            text: e.target.elements.text.value
          }
        });
      }}
    >
      <input name="text" />
      <button type="submit">Add Todo</button>
    </form>
  )
}

By calling the mutation when the form is submitted, we can create new todos!

We could also add features to update or delete todos.

And that's it - we've built a full React Apollo todo app! We've learned how to:

  • Set up a server with Apollo
  • Get Apollo Client ready
  • Connect React and Apollo Client
  • Use queries to fetch data
  • Use mutations to change data

From here, you can keep building, using more of Apollo's features like caching, subscriptions, and more!

Conclusion

React Apollo is a great tool for linking your React app with a GraphQL server. By this point, you've learned about its main features and how to use them for tasks like:

  • Getting data with queries and handling loading or error messages
  • Updating data on the server with mutations
  • Keeping track of your app's local state and making sure the UI stays up-to-date
  • Using advanced techniques for better performance, like caching and live updates with subscriptions

Now that you have the basics down, you're ready to start building real apps that make the most of GraphQL's ability to fetch a lot of related data all at once and Apollo's smart features.

Here's what you might want to try next:

  • Experiment with other React hooks provided by Apollo Client like useLazyQuery and useSubscription
  • Dive into managing your app's local state with things like reactive variables and updating the cache
  • Set up user login and access control
  • Work on handling large lists of data with pagination
  • Convert an existing app from using a REST API to GraphQL and see how it works with React Apollo
  • Get your Apollo Client app ready for the public by adding server-side rendering
  • Try using Apollo Client with React Native for building mobile apps

The world of Apollo and GraphQL is always adding new tools and features. With the basics under your belt, you can keep learning more sophisticated techniques and find new ways to make your apps better.

Remember these key points:

  • GraphQL allows you to ask for a lot of related data in one go
  • Apollo Client takes care of fetching, storing, and updating data in your React app
  • React hooks help you use queries, mutations, and live updates right in your components
  • As your app gets bigger, there are lots of ways to keep it running smoothly

With some practice, using React Apollo will start to feel natural. Enjoy exploring all the possibilities!

Appendix: Additional Resources

Here are some places where you can learn more about using React Apollo:

Documentation

  • Apollo Client Docs - This is the official guide. It has everything from basic steps to more advanced stuff.
  • GraphQL Docs - If you want to understand more about GraphQL itself, this is the place.

Tutorials

Community

Related posts

Why not level up your reading with

Stay up-to-date with the latest developer news every time you open a new tab.

Read more