DEV Community

Vladimir Novick
Vladimir Novick

Posted on

Using GraphQL with Hooks

React Hooks is a new React api, that came in 16.8 version and since then has been getting a lot of buzz. The reason for that is mostly that now we don't really need to create class components for using state or lifecycle methods. In fact you can ditch lifecycle methods completely, cause with hooks you can use useEffect for anything you've used previously for lifecycle methods.

So now when hooks are out let's see if we can use GraphQL with hooks. But before let's discuss in a nutshell how we can use GraphQL with React and Apollo.
This post will assume you have basic knowledge of GraphQL, but if you don't, you can check my free online bootcamp with 9.5h of live coding and teaching lost of aspects of GraphQL.
In the following code snippet we are setting our ApolloProvider for queries, mutations and subscriptions. Also our GraphQL API endpoint has an access key so we create an authLink and wrap our httpLink with it. for WebSocketLink we set our headers inside connectionParams.

Our GraphQL API is auto generated with hasura.io free and open source engine, so if you are interested in learning more about that you can check the following video:

In the snippet above we set up our ApolloProvider and pass it with our ApolloClient configuration. Now it's time to query our GraphQL endpoint.

We do that with Query component imported from react-apollo and providing it with render prop, which will get either query result data/error or loading states. It looks like this:

import { Query } from 'react-apollo'

export const Posts = () => (
  <Query query={getPosts}>
    {({ data, loading, error }) => {
      console.log(error);
      if (error) return null;
      if (loading)
        return <div>Loading...</div>;
      return data.posts.map(post => (
        <div>
          <h3>{post.title}</h3>
          <p>{post.content}</p>
        </div>
      ));
    }}
  </Query>
)
Enter fullscreen mode Exit fullscreen mode

Mutation will look similar but instead of having data,error and loading states it will provide mutation function as first argument. whichever data we send as an argument to this function will be passed to our GraphQL mutation


<Mutation mutation={addPost}>
      {(addPost, { data }) => (
        <div>
          <form
            onSubmit={e => {
              e.preventDefault();
              addPost({
                variables: {
                  title: title.value,
                  content: content.value,
                  authorId:
                    '2808238d-5365-4a70-af52-1de6178bb090'
                },
                refetchQueries: [
                  { query: getPosts }
                ]
              });
            }}
          >
          </form>
      </div>
    )}
</Mutation>


Enter fullscreen mode Exit fullscreen mode

Subscriptions will look pretty much the same as queries, so I won't include basic example.

It's time to change everything to work with Hooks!

Let's get back to our App.js. Nothing will change there, but instead of using

import { ApolloProvider } from 'react-apollo'
Enter fullscreen mode Exit fullscreen mode

we will use

import { ApolloProvider } from 'react-apollo-hooks'
Enter fullscreen mode Exit fullscreen mode

Now inside our Posts component we won't use Query anymore.
we will import useQuery from react-apollo-hooks and use it in the following way:

import {useQuery } from 'react-apollo-hooks';

export const Posts = () => {
  const {loading, data, error} = useQuery(getPosts);
  if (loading)
    return <div>Loading...</div>
  if (error) return <div>Error</div>;
  return data.posts.map(post => (
    <div>
      <h3>{post.subject}</h3>
      <p>{post.content}</p>
    </div>
  ));
};
Enter fullscreen mode Exit fullscreen mode

Now for mutation instead of using RenderProp we can also use useMutation from react-apollo-hooks and use it in the following manner:

  const addPostMutation = useMutation(addPost)

  return (
        <div>
          <form
            onSubmit={e => {
              e.preventDefault();
              addPostMutation({
                variables: {
                  subject: title.value,
                  content: content.value,
                  userId:
                    'a29aa6ae-8cfc-43f9-997e-73baf21835d8'
                },
                refetchQueries: [
                  { query: getPosts }
                ]
              });
            }}
          >
         </form>
       </div>
  )
Enter fullscreen mode Exit fullscreen mode

Using mutations and queries as hooks help us a lot with nesting of our Mutations and Queries. Consider this:

In this gist you see nesting of query inside a mutation.
Now take a look at implementation with hooks:

Not only it looks cleaner, we've also added setState hook to change our inputs to be connected to PostMutation state.

Now let's take a look at subscriptions.
The only thing that we need to change in our Posts component is to change getPosts query itself to be subscription

const getPosts = gql`
  subscription getPosts{
    posts {
      subject
      content
    }
  }
`;
Enter fullscreen mode Exit fullscreen mode

and import useSubscription from react-apollo-hooks instead of using useQuery

export const Posts = () => {
  const {loading, data, error} = useSubscription(getPosts, { suspend: false });
  if (loading)
    return <div>Loading...</div>
  if (error) return <div>Error</div>;
  return data.posts.map(post => (
    <div>
      <h3>{post.subject}</h3>
      <p>{post.content}</p>
    </div>
  ));
};

Enter fullscreen mode Exit fullscreen mode

react-apollo-hooks has lots of additional stuff inside like experimental Suspense support for example. In a nutshell it means that instead of getting loading state from useQuery, we now can wrap the component with Suspense and provide it with a fallback for our loader.
Like this:

export const App = (
    <ApolloProvider client={client}>
         <Suspense fallback={<div>Loading...</div>}>
          <Posts/>
        </Suspense>
    </ApolloProvider>
)
Enter fullscreen mode Exit fullscreen mode

Conclusion

So to summarize. Using GraphQL with Hooks is really straightforward and hopefully at some point we can benefit from using GraphQL with hooks at official Apollo client. Currently you can use it with react-apollo-hooks library.

Also if you are interested in learning more about GraphQL, Serverless or Web, Mobile, AR, VR or IoT in general, follow me on Youtube or on Twitter

Latest comments (1)

Collapse
 
njann profile image
Nils

Thank you!