Skip to content

Instantly share code, notes, and snippets.

@remorses
Created January 25, 2020 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save remorses/69596c29aecc2985bfd8f18ef138628f to your computer and use it in GitHub Desktop.
Save remorses/69596c29aecc2985bfd8f18ef138628f to your computer and use it in GitHub Desktop.
react-extra-hooks-article

I have always used Apollo to make graphql requests inside of react, usually doing something like this

import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';

const GET_GREETING = gql`
  query getGreeting($language: String!) {
    greeting(language: $language) {
      message
    }
  }
`;

function Hello() {
  const { loading, error, data } = useQuery(GET_GREETING, {
    variables: { language: 'english' },
  });
  if (loading) return <p>Loading ...</p>;
  return <h1>Hello {data.greeting.message}!</h1>;
}

The problem with this however is that Apollo has really a strange API in my ioinion, creating the client is a lot of work as you can see

import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';

// Instantiate required constructor fields
const cache = new InMemoryCache();
const link = new HttpLink({
  uri: 'http://localhost:4000/',
});

const client = new ApolloClient({
  // Provide required constructor fields
  cache: cache,
  link: link,

  // Provide some optional constructor fields
  name: 'react-web-client',
  version: '1.3',
  queryDeduplication: false,
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-and-network',
    },
  },
});

Also the bundle size is pretty big and the UX is not great.

So i decided to find a better way to call a simple Graphql API.

I found a simpler Graphql client, called grpahql-request, with mush smaller bundle size and better UX.

import { GraphQLClient } from 'graphql-request'

const graphQLClient = new GraphQLClient('https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr', {
  headers: {
    authorization: 'Bearer MY_TOKEN',
  },
})

const query = /* GraphQL */ `
  {
    Movie(title: "Inception") {
      releaseDate
      actors {
        name
      }
    }
  }
`
graphQLClient.request(query).then(console.log)

This code is a lot simpler as you can see, the same library works in the server too so you can do sse super easily.

Then i needed a glue code that can let me use the same hooks API that Apollo uses but with any promise, so i release react-extra-hooks on npm. This package contains some utility hooks to be used in react, among these there is usePromise:

import { usePromise } from 'react-extra-hooks'
import React from 'react'
import { GraphQLClient } from 'graphql-request'

const graphQLClient = new GraphQLClient('https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr',)

const query = /* GraphQL */ `
  {
    Movie(title: "Inception") {
      releaseDate
      actors {
        name
      }
    }
  }
`

const App = () => {
    const { result, loading, error } = usePromise(() => graphQLClient.request(query))
    if (loading) {
        return <>loading</>
    }
    return <div>{result.Movie.releaseDate}</div>
}

As you can see the usage is similar to Apollo but we are using a general usePromise function instead of useQuery.

The same thing can be done with mutations, using another hook, useLazyPromise:

import { usePromise } from 'react-extra-hooks'
import React from 'react'
import { GraphQLClient } from 'graphql-request'

const graphQLClient = new GraphQLClient('https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr',)

const query = /* GraphQL */ `
    mutation {
      createActor(name: "dsf") {
        id
      }
    }
`

const App = () => {
    const [execute, {result, loading, error }] = useLazyPromise(() => graphQLClient.request(query))
    if (loading) {
        return <>loading</>
    }
    if (result) {
        return <div>{result.id}</div>
    }
    return (
        <div>
            <button onClick={execute}>execute request</button>
        </div>
    )
}

In my opinion this is much better than Apollo, the bundle size is smaller and the code is more general.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment