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.
Top comments (3)
I gave up after too many breaking changes (at least for me...). And I do not need most of the features or could build those in myself... Now, I use fetch to do graphql queries
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