我正在用 React 构建一个在线商店,并决定在该项目中使用 React Query。任务是在缓存中显示和存储产品。我需要从这些产品中获取产品页面上所需的产品并进行渲染。有两种情况:
这是我的自定义挂钩:
// useProducts.ts
import { IProduct } from '@/interfaces/product.interface';
import ProductService from '@/services/product/product.service';
import { useQuery, useQueryClient } from '@tanstack/react-query';
export const useProducts = () => {
const queryClient = useQueryClient();
const { data, isSuccess } = useQuery({
queryKey: ['products'],
queryFn: () => ProductService.getAll({ page: 1, perPage: 9 }),
select: ({ data }) => data,
});
const getProductById = async (productId: number) => {
console.log("cached products: ", queryClient.getQueryCache().find({ queryKey: ['products'] })?.state.data?.data);
const product = data?.products.find((p) => p.id === productId);
if (!!product) return product;
try {
const response = await ProductService.getById(productId);
queryClient.setQueryData<IProduct[]>(['products'], (state) => {
console.log("state:", state);
return [...(state || []), response];
});
return response;
} catch (error) {
console.error('Error fetching product by ID:', error);
return null;
}
};
return { data, isSuccess, getProductById };
};
// ProductService.ts
import { $axios } from '@/api/api.interceptor';
import { IProduct } from '@/interfaces/product.interface';
import {
IProductResponse,
ProductDataFiltersType,
ProductDataType,
} from './product.types';
class ProductService {
private url = '/product';
getAll = async (queryData = {} as ProductDataFiltersType) => {
return $axios.get<IProductResponse>(this.url, { params: queryData });
};
getById = async (id: string | number) => {
// return $axios.get<IProduct>(`${this.url}/${id}`);
const response = await $axios.get<IProduct>(`${this.url}/${id}`);
return response.data;
};
...
}
export default new ProductService();
export type IProductResponse = {
products: IProduct[]
currentPage: number
totalPages: number
}
由于某种原因,当我调用 setQueryData 时,axios 响应处于状态而不是产品数组(因为我认为它应该有效):
cached products: {products: Array(9), totalPages: 2, currentPage: 1}
state: {data: {products, currentPage, totalPages}, status: 200, statusText: 'OK', headers: AxiosHeaders, config: {…}, …}
因此,我的错误是-
useProducts.ts:42 Error fetching product by ID: TypeError: (state || []) is not iterable
at useProducts.ts:25:21
at functionalUpdate (@tanstack_react-query.js?v=6de31b48:42:42)
at _a8.setQueryData (@tanstack_react-query.js?v=6de31b48:1538:18)
at getProductById (useProducts.ts:24:19)
顺便说一句,
products
在我的 Home.tsx 中运行完美。
import CardsContainer from '@/components/shared/CardsContainer/CardsContainer';
import { useProducts } from '@/hooks/features/products/useProducts';
import { useActions } from '@/hooks/general/useActions';
import { useEffect } from 'react';
import Banner from './components/Banner/Banner';
function Home() {
const { data, isSuccess } = useProducts();
const { checkAuth } = useActions();
useEffect(() => {
checkAuth();
}, []);
return (
<section className="rows-container">
<Banner />
{isSuccess && data?.products && (
<CardsContainer products={data.products} />
)}
</section>
);
}
export default Home;
附注
您不需要设置缓存,如果您在获取数据时提供“queryKey”,所有缓存都会由react-query自动解决。
要访问缓存数据,您可以使用
const queryClient = useQueryClient()
const data = queryClient.getQueryData(queryKey)
包“@tanstack/react-query”包含一个异步函数,可用于获取现有查询的缓存数据。如果查询不存在,将调用 fetchQuery 并返回其结果。
const data = await queryClient.ensureQueryData({ queryKey, queryFn })
您可以在此处查看文档 - https://tanstack.com/query/v4/docs/react/reference/QueryClient#queryclientensurequerydata