Introducing GraphQL Hooks


Senior Software Engineer

At NearForm we love React, and since the release of React Hooks we’ve been busy building cool new things with them.

We also love GraphQL, its declarative API is perfect to marry up with React components.

Introducing graphql-hooks:

GraphQL Hooks is a super lightweight GraphQL client for React with first-class support for hooks. It supports custom cache plugins, server-side rendering and requires minimal configuration to get up and running quickly. On top of that, it’s tiny – weighing in at 5.2KB (1.9KB gzipped).

Example:

Let’s walk through how we would get started with `graphql-hooks` by building a small demo application. In this example, we’re using create-react-app to bootstrap the React application and GraphCool to bootstrap the GraphQL API.

We’re going to cover:

  • `GraphQLClient` & `ClientContext` – how to create a client instance using the Context API
  • `useQuery` – send a GraphQL query
  • `useMutation` – send a GraphQL mutation
  • Refetching data

In the following snippet, we configure a new `GraphQLClient`, letting it know where to find our GraphQL API. We then pass our client into React’s context using the provided `ClientContext`, making it available throughout our application.  

import { GraphQLClient, ClientContext } from 'graphql-hooks'

const client = new GraphQLClient({
  url: 'https://api.graph.cool/simple/v1/cjs4qo29b2w0c0130tfx6maca'
})

function App() {
  return (
    <ClientContext.Provider value={client}>
      {/* children */}
    </ClientContext.Provider>
  )
}

useQuery

Now we will create a new component called `Posts`. This will send a query to fetch the posts from our GraphQL API using `useQuery` and render them in a list.

import React from 'react'
import { useQuery } from 'graphql-hooks'

export const allPostsQuery = `
  query {
    allPosts(first: 20) {
      id
      title
      url
    }
  }
`

export default function Posts() {
  const { loading, data, error } = useQuery(allPostsQuery)

  return (
    <>
      <h3>Posts</h3>
      <PostList loading={loading} error={error} data={data} />
    </>
  ) 
}

function PostList({ loading, error, data }) {
  if (loading) return 'Loading...'
  if (error) return 'There was an error loading the posts :('
  if (!data || !data.allPosts || !data.allPosts.length) return 'No posts'

  return (
    <ul>
      {data.allPosts.map(post => (
        <li key={post.id}>
          <a href={post.url}>{post.title}</a>
        </li>
      ))}
    </ul>
  )
}

useMutation

We can then make use of `useMutation`, by adding a small form that enables the user to add a new post to the list.

import React, { useState } from 'react'
import { useMutation } from 'graphql-hooks'

import CreatePostForm from './CreatePostForm'

const createPostMutation = `
 mutation CreatePost($title: String!, $url: String!) {
   createPost(title: $title, url: $url) {
     id
   }
 }
`

export default function CreatePost({ onSuccess }) {
  const [createPost, { loading, error }] = useMutation(createPostMutation)

  async function handleSubmit({ title, url }) {
    await createPost({ variables: { title, url } })
    onSuccess()
  }

  return (
    <CreatePostForm loading={loading} error={error} onSubmit={handleSubmit} />
  )
}

Refetching

Let’s include the `CreatePost` component inside `Posts` and make use of the `refetch` function from `useQuery`  once the mutation is complete.

export default function Posts() {
  const { loading, data, error, refetch } = useQuery(allPostsQuery)

  return (
    <>
      <h3>Add post</h3>
      <CreatePost onSuccess={refetch} />
      <h3>Posts</h3>
      <PostList loading={loading} error={error} data={data} />
    </>
  )
}

You can see the full example running here and you can find the code here.

Great, but what about caching?

Caching is a plug-in. Pass your cache implementation in when you instantiate your client, like so:

import { GraphQLClient } from 'graphql-hooks'
import memCache from 'graphql-hooks-memcache'

const client = new GraphQLClient({
  ...
  cache: memCache()
})

Here we’re using graphql-hooks-memcache, an in-memory cache.

What about Server Side Rendering?

Yup – you guessed it, graphql-hooks-ssr has you covered. Check out its documentation for a step by step guide.

What else can graphql-hooks do?

Pagination

Manually trigger a query

Customise fetch options per query/mutation

Fine-grained error handling

…and lots more! For a full list of features, see the README.

If you’d like to see some more examples you can check out our Fastify SSR and Next.js examples. We’d love for you to try it out yourselves and, as always, we welcome any feedback and contributions!

At NearForm, we have vast experience in building solutions across a broad tech stack to deliver reduced complexities and overcome common hurdles. If you are creating modern applications and leveraging web technologies, contact us to learn more about how we can help.

Photo by Clint Adair on Unsplash

nearform-news

Top