그동안 react query를 사용할 때 useQuery를 익명 함수로 한 번 더 묶어서 hook으로 분리해 사용하고는 했지만, queryKey등을 한 번 더 분리하여 관리하는 방법이 있길래 오늘 연습해봤다.
기존에 사용하던 방법
export const useProducts = () => useQuery({ queryKey: ["products"], queryFn: () => api.products.getProducts(), }) // export const useProduct = (id: number) => useQuery({ queryKey: ["products", id], queryFn: () => api.products.getProduct(id), });
이번에 시도하는 방법
const queryKeys = { products: ["products"] as const, product: (id: number) => [...queryKeys.products, id] as const, }; // const queryOptions = { products: () => ({ queryKey: queryKeys.products, queryFn: () => api.products.getProducts(), }), product: (id: number) => ({ queryKey: queryKeys.product(id), queryFn: () => api.products.getProduct(id), }), }; // export const useProducts = () => { return useQuery(queryOptions.products()); }; export const useProduct = (id: number) => { return useQuery(queryOptions.product(id)); };
// api.ts
import axios, { AxiosInstance } from "axios";
import { BrandsAPI } from "./api.brands";
import { ProductsAPI } from "./api.product";
const BASE_URL = "https://api.ballang.yoojinyoung.com";
const client = axios.create({
baseURL: BASE_URL,
headers: {
"Content-Type": "application/json",
},
withCredentials: true,
});
class API {
private client: AxiosInstance;
public products;
public brands;
constructor() {
this.client = client;
this.products = new ProductsAPI(this.client);
this.brands = new BrandsAPI(this.client);
}
}
const api = new API();
export default api;
// api.products.ts
import { AxiosInstance } from "axios";
export class ProductsAPI {
private client: AxiosInstance;
constructor(client: AxiosInstance) {
this.client = client;
}
async getProducts() {
const response = await this.client.get("/products");
return response.data;
}
async getProduct(id: number) {
const response = await this.client.get(`/products/${id}`);
return response.data;
}
}
// query.products.ts
import { useQuery } from "@tanstack/react-query";
import api from "../api/api";
const queryKeys = {
products: ["products"] as const,
product: (id: number) => [...queryKeys.products, id] as const,
};
const queryOptions = {
products: () => ({
queryKey: queryKeys.products,
queryFn: () => api.products.getProducts(),
}),
product: (id: number) => ({
queryKey: queryKeys.product(id),
queryFn: () => api.products.getProduct(id),
}),
};
export const useProducts = () => {
return useQuery(queryOptions.products());
};
export const useProduct = (id: number) => {
return useQuery(queryOptions.product(id));
};