React Hooks in Apollo Client for GraphQL Queries and Mutations
Tags: react, webdev, javascript, node
Published: 2020-01-09 14:14:15

---
title: React Hooks in Apollo Client for GraphQL Queries and Mutations
published: true
description: How to use React Hooks with GraphQL and Apollo client. React hooks for GraphQL queries and mutations.
tags: react, webdev, javascript, node
series: atheros
canonical_url: https://atheros.ai/blog/react-hooks-in-apollo-client-for-graphql-queries-and-mutations
---

## Introduction

The hype following the last React conference has diminished. The proposal for React Hooks was introduced as part of the React alpha release. Since React v16.8, React Hooks have been in all <a href="https://reactjs.org/blog/2019/02/06/react-v16.8.0.html" title="React official release" >official release</a> as well. How does this improvement affect how we build our apps with GraphQL? We usually take our time before introducing new tech features in our projects at <a title="Atheros Intelligence official company website"  href="https://atheros.ai">Atheros</a>. This will allow us to not jump on the false hypes. React Hooks are now tested and production-ready, so we took a shot on implementing it in our projects as well. React Hooks is a new way how to reduce the need for React component classes and their life-cycle methods. They also solve other problems related to using <a title="HOC (Higher order component)"  href="https://reactjs.org/docs/higher-order-components.html">HOC (Higher order component)</a> or <a  href="https://reactjs.org/docs/render-props.html">render props pattern</a>. There are a lot of resources on React Hooks and I will not go deep into them from React standpoint in this article. You can check out the following talk from the recent conference

{% youtube dpw9EHDh2bM %}

or the <a title="React official documentation"  href="https://reactjs.org/docs/hooks-intro.html">official documentation</a>

The official React library comes with its own default Hooks such as <a title="React Hooks overview"  href="https://reactjs.org/docs/hooks-overview.html">**useState**, **useContext**, **useEffect** and others</a>. But, The React library does not, however, contain Hooks for executing GraphQL queries and mutations in the Apollo client. Let's take a look at these now. First, let's summarize how we currently fetch data with Apollo and React.

## Apollo client API

With the Apollo client and React, you can query your GraphQL server in various ways. We currently have three major ways to query our GraphQL server.

* **HOC pattern**
* **Render props pattern**
* **React Hooks**

We will show how these approaches work using the simple component for displaying a list of emails. The GraphQL query looks like this:

``` graphql
query Subscriptions {
  subscriptions {
    id
    email
    source
  }
}
```

It will be useful to <a title="Next, React, GraphQL, Apollo Hook starter kit"  href="https://github.com/atherosai/next-react-graphql-apollo-hooks">check out the repository</a> with examples. You can clone the repository with...

``` bash
git clone git@github.com:atherosai/next-react-graphql-apollo-hooks.git
```

and then, to preserve **package-lock.json** dependencies, install with...

``` bash
npm ci
```

You can run dev server as follows...

``` bash
npm run dev
```

## HOC (Higher-Order-Component) pattern

As far as I know, this is the oldest execution method for queries and mutations with Apollo. It uses the well-known <a title="Higher order functions"  href="https://reactjs.org/docs/higher-order-components.html">React HOC pattern</a>. This pattern is implemented in React Apollo using the **HOC component** created with the <a  title="GraphQL function"  href="https://www.apollographql.com/docs/react/api/react-apollo#graphql-query-options">graphql function</a>. We can use this function to define further HOCs for a different GraphQL query or mutation. With this approach, we can write our simple component as follows:

``` javascript
import React from 'react';
import { graphql } from '@apollo/react-hoc';
import get from 'lodash.get';
import SUBSCRIPTIONS_QUERY from './Subscriptions.graphql';
import s from './SubscriptionTable.scss';
const withSubscriptionQuery = graphql(SUBSCRIPTIONS_QUERY);
const SubscriptionsTable = ({ data }) => {
    return (
    <div className={s.SubscriptionTable}>
        <div className={s.SubscriptionTable__Header}>Email</div>
        {get(data, 'subscriptions', []).map(subscription => (
            <div key={get(subscription, 'id')} className={s.SubscriptionTable__Row}>
            {get(subscription, 'email')}
            </div>
        ))}
    </div>
    );
};
export default withSubscriptionQuery(SubscriptionsTable);
```

The disadvantage can be that if we have many mutations or queries, it can become impractical to maintain so many HOCs. In some cases, you even need to keep the HOCs in order if you use, for example, the **with Apollo** component as well. In these cases, to clean up the code we can use <a title="Apollo compose utility"  href="https://www.apollographql.com/docs/react/api/react-apollo#compose">compose utility</a> from the React Apollo package, or just use the <a  href="https://github.com/acdlite/recompose">recompose</a> library.

## Render props pattern

This pattern was official one for quite some time in Apollo community. There is no need to wrap the components with HOCs. The HOCs created with **graphql()** had been replaced by the **Query** and **Mutation** components. The rewrite for our simple component above is easy.

``` javascript
import React from 'react';
import { Query } from '@apollo/react-components';
import get from 'lodash.get';
import SUBSCRIPTIONS_QUERY from './Subscriptions.graphql';
import s from './SubscriptionTable.scss';
const SubscriptionsTable = () => {
    return (
        <Query query={SUBSCRIPTIONS_QUERY}>
        {({ loading, error, data }) => {
            if (loading) return "Loading...";
            if (error) return \`Error! ${error.message}\`;
            
            return (
            <div className={s.SubscriptionTable}>
                <div className={s.SubscriptionTable__Header}>Email</div>
                {get(data, 'subscriptions', []).map(subscription => (
                    <div key={get(subscription, 'id')} className={s.SubscriptionTable__Row}>
                    {get(subscription, 'email')}
                    </div>
                ))}
            </div>)
        }}
        </Query>

    );
};
export default SubscriptionsTable;
```

You are still able to use either HOCs or render props in Apollo client, but both ways are now obsolete and replaced with official React Hooks. You can also check out this article on <a  title="Pros and const of HOC, render props and React Hooks" href="https://pawelgrzybek.com cross-cutting-functionality-in-react-using-higher-order-components-render-props-and-hooks/">pros and cons of higher-order components, render props, and React Hooks</a>.

## Using React Hooks with GraphQL in the Apollo client

> This section was significantly updated to be compliant with official Apollo client API

React Hooks now have official support in the <a title="React Apollo"  href="https://github.com/apollographql/react-apollo">React Apollo</a>. The support of React Hooks is coming with some great improvements. First of all there is significant reduction in bundle size as you can use only <a title="Official React Hooks Apollo library "  href="https://www.npmjs.com/package/@apollo/react-hooks">@apollo/react-hooks</a> package. Even though you can reinvent the wheel and try to prepare the Hooks by yourself, I would suggest to use already-prepared Hooks. With the new introduction of React Hooks in Apollo official release you would need to install dedicated packages for <a  title="React server side rendering" href="https://www.apollographql.com/docs/react/api/react-ssr/">SSR</a>. The first thing that you need to do is to wrap your top-level component with the Apollo provider. We use <a title="Next.js official website" href="https://nextjs.org/">Next.js</a> in our <a title="Example project" href="https://github.com/atherosai/next-react-graphql-apollo-hooks">example project</a>, so a good place to do it can be in **__app.js** file as follows:

``` javascript
import React from 'react';
import get from 'lodash.get';
import App, { Container } from 'next/app';
import { ApolloProvider } from '@apollo/react-hooks';
import Router from 'next/router';
import { pageview } from '../lib/gtag';
import { NODE_ENV, CUSTOM_ENV } from '../config/config';
import withApolloClient from '../lib/with-apollo-client';
import globalStyle from '../theme/global.scss';
if (CUSTOM_ENV === 'production') {
  Router.onRouteChangeComplete = url => {
    pageview(url);
  };
}
class MyApp extends App {
  componentDidMount() {
    import('webfontloader').then(WebFont =>
      WebFont.load({
        google: {
          families: ['Montserrat']
        }
      })
    );
    if ('serviceWorker' in navigator && NODE_ENV === 'production') {
      get(navigator, 'serviceWorker').register('/service-worker.js');
    }
  }
  render() {
    const { Component, pageProps, apolloClient } = this.props;
    return (
      <Container>
        <ApolloProvider client={apolloClient}>
          <div className={globalStyle.Global}>
            <Component {...pageProps} />
          </div>
        </ApolloProvider>
      </Container>
    );
  }
}
export default withApolloClient(MyApp);
```

However, this is only good approach if you use Next.js with server side rendering (SSR) and fetch data from GraphQL on majority of your pages. For pages that do not need to be server side rendered you can use HOC to inject Apollo Provider on per page bases as follows:

``` typescript
import React from 'react';
import { ApolloProvider } from '@apollo/react-hooks';
import ApolloClient from 'apollo-client';
import { NormalizedCacheObject } from 'apollo-cache-inmemory';
import { IS_PROD } from '../config/config';
import initApollo from './init-apollo';


interface AppPropsI {
  apolloClient: ApolloClient<NormalizedCacheObject>;
}

interface ApolloPropsI {
  apolloState: NormalizedCacheObject;
}
// should be used for pages, which should not be server side renderer
const withApolloClientStatic: Function = (App: React.FunctionComponent<AppPropsI>) => {
  const Apollo: React.FunctionComponent<ApolloPropsI> = ({ apolloState }: ApolloPropsI) => {
    const apolloClient = initApollo(apolloState);
    return (
      <ApolloProvider client={apolloClient}>
        <App apolloClient={apolloClient} />
      </ApolloProvider>
    );
  };

  // Set the correct displayName in development
  if (!IS_PROD) {
    const displayName = Apollo.displayName || Apollo.name || 'Component';

    if (displayName === 'App') {
      // eslint-disable-next-line no-console
      console.warn('This withApollo HOC only works with PageComponents.');
    }

    Apollo.displayName = `withApollo(${displayName})`;
  }

  return Apollo;
};

export default withApolloClientStatic;
```

The **Apollo Provider** enables us to use React Hooks for executing queries and mutations in our application. The following Hooks are available in the official Apollo release: **useQuery, useLazyQuery, useMutation, useSubscription** and **useApolloClient**.

## GraphQL queries with <a title="React Apollo Hooks library"  href="https://www.npmjs.com/package/@apollo/react-hooks">React Apollo Hooks</a>

Let's take a look at the component for fetching emails that we wrote with the **HOC** and **render props pattern**. We will import the **useQuery** Hook from the officialReact Apollo Hooks library. Now let's define our first Hook for a GraphQL query. Hooks need to be defined in the body of functional React components. The new implementation with React Hooks is as follows:

``` typescript
import React from 'react';
import get from 'lodash.get';
import uuid from 'uuid/v1';
import { useQuery } from '@apollo/react-hooks';
import SUBSCRIPTIONS_QUERY from './SUBSCRIPTIONS.graphql';
import { SubscriptionsQuery, SubscriptionsQueryVariables } from '../../../__generated__/typescript-operations';
import s from './SubscriptionsTable.scss';

const SubscriptionsTable: React.FunctionComponent = () => {
  const { data, loading, error } = useQuery<SubscriptionsQuery,
  SubscriptionsQueryVariables>(SUBSCRIPTIONS_QUERY);

  if (loading) return <>Loading...</>;
  if (error) return <>{`Error! ${error.message}`}</>;

  return (
    <div className={s.SubscriptionTable}>
      <table>
        <thead>
          <tr>
            <th>Email</th>
            <th>Source</th>
          </tr>
        </thead>
        <tbody>
          {data && data.subscriptions && data.subscriptions.map((subscription) => (
            <tr key={get(subscription, 'id', uuid())}>
              <td>
                {get(subscription, 'email')}
              </td>
              <td>
                {get(subscription, 'source')}
              </td>
            </tr>
          ))}
        </tbody>
      </table>

    </div>
  );
};

export default SubscriptionsTable;
```

We can see that the API is simple to use, and also the **useQuery** Hook returns the same variables as usual. You might also notice that we have pre-generated our TypeScript types. For more information you can follow our <a href="/blog/generate-javascript-static-types-from-graphql-typescript-and-flow" title="Generate Static Types from GraphQL schema">previous article</a>.

Now let's take a look at how we can define variables and manually update the cache.

## Writing our GraphQL mutations with React Hooks

We can define the **useMutation** in a similar way. As we know, the main difference between a query and a mutation lies in their different execution. Queries are executed in parallel, but mutations are executed serially. Let's take a look at how to execute the **subscribeEmail** mutation

``` graphql
mutation Subscribe($input: SubscribeInput!) {
  subscribe(input: $input) {
    id
    email
    source
  }
}
```

using the **useMutation** Hook.

``` typescript
/* eslint-disable jsx-a11y/label-has-for */
import React from 'react';
import { useMutation } from '@apollo/react-hooks';
import {
  Formik, ErrorMessage, Form, Field,
} from 'formik';
import * as Yup from 'yup';
// eslint-disable-next-line import/no-extraneous-dependencies
import { FetchResult } from 'apollo-link';
import get from 'lodash.get';
import s from './Subscription.scss';
import SUSCRIBE_MUTATION from './SUBSCRIBE.graphql';
import SUBSCRIPTIONS_QUERY from '../SubscriptionsTable/SUBSCRIPTIONS.graphql';
import { SubscribeMutation, SubscribeMutationVariables, Query } from '../../../__generated__/typescript-operations';

interface InitialValuesI {
  email: string;
}
interface HandleSubscribeI {
  values: InitialValuesI;
  subscribeMutation: Function;
  resetForm: Function;
}


const handleSubsribe: Function = async ({
  values,
  subscribeMutation,
  resetForm,
}: HandleSubscribeI) => {
  const subscribeResult: Promise<SubscribeMutation> = await subscribeMutation({
    variables: {
      input: {
        source: 'HOME_PAGE',
        ...values,
      },
    },
  });

  if (get(subscribeResult, 'data.subscribe')) {
    resetForm();
  }

  return subscribeResult;
};


const Subscription: React.FunctionComponent = () => {
  const [subscribeMutation] = useMutation<SubscribeMutation, SubscribeMutationVariables>(
    SUSCRIBE_MUTATION,
    {
      update: (cache, { data }: FetchResult): void => {
        const dataResult = cache.readQuery<Query>({ query: SUBSCRIPTIONS_QUERY });
        cache.writeQuery({
          query: SUBSCRIPTIONS_QUERY,
          data: {
            subscriptions: dataResult
            && dataResult.subscriptions
            && dataResult.subscriptions.concat([data && data.subscribe]),
          },
        });
      },
    },
  );
  const initialValues: InitialValuesI = {
    email: '',
  };
  return (
    <div className={s.Subscription}>
      <div className={s.Subscription__SubscriptionWrapper}>
        <div>
          <h2>
            Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing
            industries for previewing layouts and visual mockups.
          </h2>
          <Formik
            initialValues={initialValues}
            onSubmit={async (values, { resetForm }): Promise<SubscribeMutation> => handleSubsribe({
              values,
              subscribeMutation,
              resetForm,
            })}
            validationSchema={Yup.object().shape({
              email: Yup.string()
                .email()
                .required('Before submitting you need to provide your email'),
            })}
          >
            <Form>
              <div className={s.Subscription__Row}>
                <label htmlFor="email">Email</label>
                <Field
                  id="email"
                  className={s.Carousel__EmailInput}
                  name="email"
                  placeholder="your@email.com"
                  type="email"
                />
                <button type="submit" className={s.Subscription__SubscribeButton}>
                    Subscribe
                </button>
              </div>
              <div className={s.Subscription__FieldErrorRow}>
                <ErrorMessage
                  name="email"
                  component="div"
                  className={s.Subscription__FieldError}
                />
              </div>
            </Form>
          </Formik>
        </div>
      </div>
    </div>
  );
};

export default Subscription;
```

We have written our component with the excellent <a title="Formik library"  href="https://github.com/jaredpalmer/formik">Formik</a> and <a title="Yup library"  href="https://github.com/jquense/yup">Yup</a> validation library. We can see that the Hooks definition is done without variables. In the React Apollo library, we can either define variables in the body of a functional component or pass them dynamically once the Hook is executed.

## Conclusion

I hope that you like this short article on using React Hooks with GraphQL. We really enjoy using Hooks with <a title="React Apollo Hooks trojanowski"  href="https://github.com/trojanowski/react-apollo-hooks">unofficial community library</a> and now with official Apollo support it gets even better. To ease your Hooks set-up with Apollo, you can use our <a title="Example repository"  href="https://github.com/atherosai/next-react-graphql-apollo-hooks">example repository</a> to speed up the process.

> Did you like this post? You can clone <a title="Github repository" href="https://github.com/atherosai/next-react-graphql-apollo-hooks">the repository with the examples and project set-up here</a>.
> Feel free to send any questions about the topic to <a href="mailto:david@atheros.ai" title="Contact">david@atheros.ai</a>.

This article was originally published at https://atheros.ai/blog/react-hooks-in-apollo-client-for-graphql-queries-and-mutations