Tanstack React Query 中更新数据的问题

问题描述 投票:0回答:1

我正在用 React 构建一个在线商店,并决定在该项目中使用 React Query。任务是在缓存中显示和存储产品。我需要从这些产品中获取产品页面上所需的产品并进行渲染。有两种情况:

  1. 产品在缓存中 - 我从缓存中检索它并从函数返回它。
  2. 它不在缓存中 - 我从服务器获取它,将其加载到缓存中,然后从函数返回它。 问题是我不明白如何更新缓存中的数据。

这是我的自定义挂钩:

// 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;

附注

  1. 您能给新手解释一下 setQueryData 和 setQueriesData 之间的区别吗?
  2. 有没有办法让我看到React Query存储在缓存中的数据(也许有一些扩展)?
reactjs react-query tanstackreact-query
1个回答
0
投票
  1. 您不需要设置缓存,如果您在获取数据时提供“queryKey”,所有缓存都会由react-query自动解决。

  2. 要访问缓存数据,您可以使用

    const queryClient = useQueryClient()
    const data = queryClient.getQueryData(queryKey)

  3. 包“@tanstack/react-query”包含一个异步函数,可用于获取现有查询的缓存数据。如果查询不存在,将调用 fetchQuery 并返回其结果。

    const data = await queryClient.ensureQueryData({ queryKey, queryFn })
    您可以在此处查看文档 - https://tanstack.com/query/v4/docs/react/reference/QueryClient#queryclientensurequerydata

© www.soinside.com 2019 - 2024. All rights reserved.