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):
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 function returns a custom React hook with 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!
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
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>
)
}