You don't need Apollo to use Graphql in react
Tags: react, graphql, apollo
Published: 2020-01-25 14:57:56

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

```tsx
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:

```tsx
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.

```tsx
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`:

```tsx
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`:

```tsx
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.