⚛ React Query
29 Jan, 2023
👋 FYI, this note is over 6 months old. Some of the content may be out of date.
On this page
useQuery Jump to heading
Given a fetch function like this (that uses axios):
import axios from 'axios'
import urlJoin from 'proper-url-join'
export interface APIResponse<T> {
status?: number
success: boolean
data?: T
error?: ErrorResponse
}
export interface ErrorResponse {
message: string
data?: {
errors?: unknown
error?: unknown
}
}
interface RequestModel {
path: string
}
export const getSomeData = async <Response>({
path,
}: RequestModel): Promise<APIResponse<Response>> => {
try {
const { data } = await axios({
method: 'GET',
url: urlJoin('https://mysite.com', path),
})
return data
} catch (error) {
throw new Error(error.message || 'error.unknown')
}
}
This is how you might use react-query
import { useQuery, UseQueryResult } from 'react-query'
interface ResponseModel {
data: {
key: string
}
}
type ResponseUseQueryModel = UseQueryResult<ResponseModel, Error>
const someData = useQuery<ResponseUseQueryModel, Error>(
['traineeFeedback', traineeId],
() =>
getSomeData<TraineeFeedbackDataModel>({
path: TRAINEE_FEEDBACK,
})
)
Add options to the query Jump to heading
const someData = useQuery<ResponseUseQueryModel, Error>(
['traineeFeedback', traineeId],
() =>
getSomeData<TraineeFeedbackDataModel>({
path: TRAINEE_FEEDBACK,
}),
// options are the 3rd param
{
// will wait for `idToken` to be truthy before running this query
enabled: !!idToken,
}
)
As a custom hook Jump to heading
import { useQuery, UseQueryResult } from 'react-query'
export const useTraineeFeedback = (
traineeId: string,
idToken: string
): UseQueryResult<TraineeFeedbackResponseModel, Error> => {
return useQuery<TraineeFeedbackResponseModel, Error>(
['traineeFeedback', traineeId],
() =>
getSomeData<TraineeFeedbackDataModel>({
path: TRAINEE_FEEDBACK,
}),
{
enabled: !!idToken,
}
)
}
Usage in a component Jump to heading
From here
interface ViewUserPagePathParameters {
userId: string
}
interface IUser {
id: string
displayName: string
}
export function assertNever(value: never): never {
throw new Error(`Unhandled discriminated union member: ${value}`)
}
export const ViewUser: React.FC = (props) => {
const { userId } = useParams<ViewUserPagePathParameters>()
const { status, data, error } = useQuery<IUser, Error>(
`getUser for ${userId}`,
() => getUser({ id: userId })
)
if (status === 'success') {
const user = data
return <div>Name: {user.displayName}</div>
} else if (status === 'loading') {
return <div>loading...</div>
} else if (status === 'idle') {
return <div>mutating...</div>
} else if (status === 'error') {
return 'An error has occurred: ' + error.message
} else {
return assertNever(queryResult)
}
}
useQueries Jump to heading
import { useQueries } from 'react-query'
const scorecardQueries = useQueries([
{
queryKey: ['traineeInfo', traineeId],
queryFn: () =>
getSomeData<GetTraineeInfoDataModel>({
path: TRAINEE_FEEDBACK,
}),
// options in useQueries are not in a separate object
enabled: !!idToken,
},
{
queryKey: ['traineeAchievements', traineeId],
queryFn: () =>
getSomeData<TraineeAchievementsDataModel>({
path: TRAINEE_FEEDBACK,
}),
enabled: !!idToken,
},
])
← Back home