GraphQL Hasura with React Query-useMutation & useQuery Hooks — Part 2

Yogeshwar Tanwar
4 min readOct 15, 2021

This article focuses on `useQuery` & `useMutation` hooks of React Query

1. useQuery — use this hook when we want to fetch data from remote server or any other source

Call useQuery hook with at least :

  • Unique Key name for query
  • Function returning Promise which either resolves data or throws error

Let’s talk about code implementation now .We have folder hasura-graphqlwith file queries/user.js which contains graphql query for Hasura hosted instance which we created in previous article and another folder react-query which contains queries/user.js . In this we have useQuery hook which wraps graphql query.

  • hasura-graphql/queries/user.js contains below code -
import graphQLRequest from '../service'const userData = async ({ email }) => {
try {
const query = `
query User($email:String!) {
users_by_pk(email:$email) {
name
email
}
}
`
const qv = { email: email }
const user = await graphQLRequest({
query,
variables: qv
})
return user
} catch (error) {
throw error
}
}
export { userData }

In above code we have created a graphql query to fetch users email & name and calling that query via graphQLRequest wrapper function

  • react-query/queries/user.js contains below code -
import { useQuery } from 'react-query'
import { userData } from '../../hasura-graphql/queries/user'
async function userProfile(email) {
const data = await userData({ email })
return data
}
function useUserData() {
return useQuery(['userData'], userProfile, {
initialData: {
name: 'test_user',
email: 'test@test.com',
},
initialStale: true,
refetchOnMount: true,
refetchOnWindowFocus: false,
})
}
export { useUserData }

In above code we have used useQuery hook with userData as key & userProfile as function which is calling userData() function from hasura-graphql/queries/user.js

Now we can import & call above hook anywhere in our app , for reference we are calling it in App.js as follows

import { useUserData } from './react-query/queries/user'  // query user
const { status: userDataStatus,
data: userData,
error: userDataErr
} = useUserData()
useEffect(
() => {
console.log(userDataStatus, userData, userDataErr)
},
[ userData, userDataErr, userDataStatus ])

That’s all with useQuery , in case for more complex use cases have a look at documentation.

2. useMutation — use this hook to perform server side-effects or create/update/delete data

Similar to query , we have folder named hasura-graphqlwith file mutations/user.js which contains graphql mutation for Hasura which insert user with email, name as parameters and another folder name react-query which contains mutations/user.js which has useMutation hook which wraps above graphql mutation.

  • hasura-graphql/mutations/user.js contains below code -
import graphQLRequest from '../service'async function updateUserProfile({ email, name }) {
try {
const query = `
mutation addUser($email:String!,$name:String!,) {
insert_users(objects: {email: $email, name: $name, }}}) {
affected_rows
returning {
email
}
}
}`
const qv = { email: email, name: name }
const data = await graphQLRequest({ query, variables: qv })
return data
} catch (error) {
throw error
}
}
export { updateUserProfile }
  • react-query/mutations/user.js contains below code -
import { useMutation } from 'react-query'
import { updateUserProfile } from '../../hasura-graphql/mutations/user'
const useUpdateUserData = () =>
useMutation(
async (data) => {
return await updateUserProfile(data)
},
{
onMutate: (editedValue) => {
// console.log(data, error, editedValue)
},
onError: (error, editedValue) => {
console.log(error, editedValue)
},
onSettled: (data, error, editedValue) => {
// console.log(data, error, editedValue)
},
onSuccess: (data, variables) => {
// console.log(data, variables)
}
}
)
export { useUpdateUserData }

In above code we have used useMutation hook which is calling hasura graphql mutation side effects and giving below event function -

  • onMutate — A mutation is about to happen
  • onError — Error happend
  • onSettled — Always executes irrespective of Error/Success
  • onSuccess — Success in Execution

Now we can import & call above hook anywhere in our app , for reference we are calling it in App.js as follows -

import { useUpdateUserData } from './react-query/mutations/user'// mutate user
const {
mutateAsync: updateUser,
status: userUpdateStatus,
isLoading: isLoadingUserUpdate,
data: userUpdateData,
error: userUpdateErr
} = useUpdateUserData()
useEffect(() =>
{ console.log()},
[ userUpdateData, userUpdateErr,
isLoadingUserUpdate, userUpdateStatus ]
)
// call mutate function with input parameters
updateUser({ email, name })

A mutation can only be in one of the following states at any given moment:

  • status === 'idle' - The mutation is currently idle state
  • status === 'loading' - The mutation is currently running
  • status === 'error' - The mutation encountered an error
  • status === 'success' - The mutation was successful and mutation data is available

Beyond those primary states, more information is available depending on the state of the mutation:

  • error - If the mutation is in an error state, the error is available via the error property.
  • data - If the mutation is in a success state, the data is available via the data property.

That’s all with useQuery , in case for more complex use cases have a look at documentation

References —

- Full code available here

- React Query official docs

--

--