loading...
Cover image for You don't need Apollo to use Graphql in react

You don't need Apollo to use Graphql in react

remorses profile image Tommaso De Rossi ・2 min read

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 become really bloated over time, making its bundle size big and its API unfriendly.
Creating a simple grahpql client is a pain:

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.

Discussion

markdown guide
 

Curious to know your opinion on this? Do you feel relay is too restrictive, also too heavy?

kesne.github.io/svelte-relay/

 

By the tome i wrote this post new libraries like swr and react query emerged, check them out