Open reboottime opened 1 month ago
Guidelines
Design and name your service member functions around resources.
Group your React Query query/mutation functions around resources, and mirror the service member names for your React Query hooks.
Group your React Query keys using an array, as query key drives query, to know more, read this
Export variables
Other than the queries/mutations hooks
export both the HTTP client instance and the grouped query keys
The why: bring convenience to where you use it
<Link
className="block card card--link"
onMouseEnter={() => {
queryClient.prefetchQuery({
queryKey: credentialQueryKeys.orders(order.id),
queryFn: () => ordersClient.geOrderById(order.id),
});
}}
to={`/orders/${order.id}`}
>
<OrderCard {...order} className="h-[152px]" />
</Link>
Example
interface GetAllOrdersParams {
status?: "pending" | "processing" | "completed" | "cancelled";
sortBy?: "createdAt" | "totalAmount";
sortOrder?: "asc" | "desc";
page?: number;
limit?: number;
}
class Orders {
private httpClient: HttpClient;
constructor(baseUrl: string) {
this.httpClient = new HttpClient(baseUrl);
}
// Query all orders
async getAllOrders(params?: GetAllOrdersParams): Promise<Order[]> {
// your code
}
// Query order by ID
async getOrderById(orderId: string): Promise<Order> {
// your code
}
// Create a new order
async createOrderById(orderData: OrderData): Promise<Order> {
// Your code
}
// Update an existing order
async updateOrderById(
orderId: string,
updateData: Omit<Partial<Order>, "id">
): Promise<Order> {
// Your code
}
// Delete an order
async deleteOrderById(orderId: string): Promise<void> {
// your code
}
}
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Orders, GetAllOrdersParams, OrderData, Order } from "./order.services";
import queryClient from 'setup/query-client';
export const ordersHttpClient = new Orders("your-base-url");
export const ordersQueryKeys = {
orders: ['orders'],
allOrders: (params) => [...ordersQueryKeys.orders, parmas],
orderById: (orderId:string) => [ordersQueryKeys.orders, orderId],
}
// export data prefetch method, to preload data. Corresponding http request will not be made if data already cahced
export const prefetchAllOrders = (params: Record<string, any>) {
return queryClient.fetchQuery({
queryKey: ordersQueryKeys.allOrders(params),
queryFn: () => ordersHttpClient.getOrders(params)
})
}
// export data prefetch method, to preload data. Corresponding http request will not be made if data already cahced
export const prefetchOrderById = (orderId: Order['id']) => {
return queryClient.fetchQuery({
queryKey: ordersQueryKeys.orderById(orderId),
queryFn: () => ordersHttpClient.getOrderById(orderId)
});
}
export const invalidateOrders = () => {
return queryClient.invalidate
}
const useAllOrders = (params?: GetAllOrdersParams) => {
return useQuery(["orders", params], () =>
ordersHttpClient.getAllOrders(params)
);
};
const useOrderById = (orderId: string) => {
return useQuery(["order", orderId], () =>
ordersHttpClient.getOrderById(orderId)
);
};
const useCreateOrder = () => {
const queryClient = useQueryClient();
return useMutation(
(orderData: OrderData) => ordersHttpClient.createOrderById(orderData),
{
onSuccess: () => {
queryClient.invalidateQueries(["orders"]);
},
}
);
};
const useUpdateOrder = () => {
const queryClient = useQueryClient();
return useMutation(
({
orderId,
updateData,
}: {
orderId: string;
updateData: Omit<Partial<Order>, "id">;
}) => ordersHttpClient.updateOrderById(orderId, updateData),
{
onSuccess: () => {
queryClient.invalidateQueries(["orders"]);
queryClient.invalidateQueries(["order"]);
},
}
);
};
const useDeleteOrder = () => {
const queryClient = useQueryClient();
return useMutation(
(orderId: string) => ordersHttpClient.deleteOrderById(orderId),
{
onSuccess: () => {
queryClient.invalidateQueries(["orders"]);
queryClient.invalidateQueries(["order"]);
},
}
);
};
Configure your query and query client default options based on your needs:
staleTime
: Set the time after which the cached data is considered stale and needs to be refetched.retry
: Define the strategy for retrying failed requests.For example, for a real-time visualization monitoring dashboard, you may want:
refetchOnWindowFocus
: Refetch data when the browser tab becomes visible.staleTime
: Set to the desired refresh frequency for real-time data.import { onlineManager } from '@tanstack/react-query'
Overview
What this article is about
This article summarizes the best practices for designing a React app using @tanstack/react-query, under the premise that your restful APIs are well designed. If your API is not resource-oriented and driven by client, consider using GraphQL instead.
The react query version discussed in this article is
5.37.1
.Why @tankstac/react-query?
Upon watching this youtube video, presented by @tanstack/react-query author Tanner Linsley, you will get a brief idea about what problems pushed the born of @tanstack/react-query.
And get what bens @tanstack/react-query brings to u via reading the motivation article
React Query Best Practices