Docs
GraphQL

GraphQL

You can send GraphQL requests using the useGql hook or by creating a client with queryProvider

useGql

First, create a query using the gql function (this helps with static typing, we'll cover that later) :

queries/users.ts
import { gql } from 'http-react'
 
const users = gql`
  query {
    users {
      name
      info {
        phone
      }
    }
  }
`
 
export default users

Use the useGql hook to use that query:

import { useGql } from 'http-react'
 
// The users query
import users from 'queries/users'
 
export default function Users() {
  const { data, loading } = useGql(users)
 
  if (loading) return <p>Loading</p>
 
  if (data.errors) {
    console.log(data.errors)
    return <p>There was an error</p>
  }
 
  return (
    <div>
      {data.data.users.map((user) => (
        <div key={user.id}>
          <h2>{user.info.phone}</h2>
        </div>
      ))}
    </div>
  )
}
💡

By default, the id of that request (used for request deduplication and sync) will be the query itself. If you need to use the same query with different variables, pass another id property when using the useGql hook:

function Component1() {
  const { data } = useGql(q, {
    id: 'query1'
  })
}
 
function Component2() {
  const { data } = useGql(q, {
    id: 'query2'
  })
}
 
// Both components use the same query but they send different requests

Sending variables

It's possible to send variables too. Just pass them in the variables property of the useGql config

import { useGql } from 'http-react'
 
import users from 'queries/users'
 
export default function Users() {
  const { data, loading } = useGql(users, {
    variables: {
      id: 10
    }
  })
 
  if (loading) return <p>Loading</p>
 
  if (data.errors) {
    console.log(data.errors)
    return <p>There was an error</p>
  }
 
  return (
    <div>
      <pre>Variables sent: {JSON.stringify(data.variables)}</pre>
      {data.data.users.map((user) => (
        <div key={user.id}>
          <h2>{user.info.phone}</h2>
        </div>
      ))}
    </div>
  )
}

Changing graphqlPath

By default, useGql sends requests to the /graphql url. This can be changed by passing graphqlPath:

import { useGql } from 'http-react'
 
import users from 'queries/users'
 
export default function Users() {
  const { data, loading } = useGql(users, {
    variables: {
      id: 10
    },
    graphqlPath: '/graphql/v2'
  })
 
  // Your jsx here
}

queryProvider

This is a function that returns a custom React hook that has static typing

Creating a client

You can create a client easily and add configurations such as headers, baseUrl, default variables values, etc:

For this, we will be using TypeScript!

shared/client.tsx
import { queryProvider, gql, defaultCache } from 'http-react'
 
type UserType = {
  name: string
}
type UserVariables = {
  id: number
}
 
// The first type argument is used for `data` and the second one for `variables`
const user = gql<UserType, UserVariables>`
  query {
    user {
      name
    }
  }
`
// static type of 'data' and 'variables' will be 'any'
const tasks = gql`
  query {
    tasks {
      completed
    }
  }
`
 
// Placing all queries together
const queries = {
  user,
  tasks
}
 
// Creating a query provider hook
const useAppQuery = queryProvider(queries, {
  config: {
    cacheProvider: defaultCache,
    headers: {
      // Headers for all queries
    }
  },
  defaults: {
    tasks: {
      // Default variables values
      variables: {
        search: ''
      },
      // The default value (works with SSR)
      value: [],
      headers: {
        Authorization: 'Token token-for-tasks'
      },
      baseUrl: 'https://api.com/v1',
      graphqlPath: '/graphql-v1'
    },
    user: {
      variables: {}, // We'll get a typescript error because we are missing 'id'!
      value: {
        name: ''
      }
    }
  }
})
 
export default useAppQuery

Learn more about cacheProvider

Using the client

You can now use the hook created with queryProvider

App.tsx
import useAppQuery from 'shared/client'
 
export default function App() {
  const { data, error } = useAppQuery('user', {
    defaut: {}, // A typescript error will show because 'name' is not present!
    variables: {} // Also a typescript error, we are missing id!
  })
 
  if (data.errors || error) return <p>Error</p>
 
  return (
    <div>
      {/* This has static typing */}
      <h2>{data.data.name}</h2>
    </div>
  )
}

If you try to use a string that does not exists in the queries object, you will get a typescript error!

useQuery('$user') // Will show an error
💡

The code above will show the following error: txt Argument of type '"$user"' is not assignable to parameter of type '"tasks" | "user"'

useData

The useData hook has full TypeScript support when passing a query created with gql. For instance, let's use the user query:

import { useData } from 'http-react'
import queries from 'shared/client.tsx'
 
function App() {
  // Has static typing
  const { name } = useData(queries.user) || {}
 
  const error = useError(queries.user)
 
  if (error) return <p>Error</p>
 
  return (
    <div>
      <h2>Name</h2>
    </div>
  )
}
Last updated on April 2, 2023