我无法在useQuery的fetchData中立即更新我的url,我该怎么办?

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

但是我什么时候去取 获取网址已过时,仅在下一次渲染时正确。

console.log('获取网址:', url.href);

在浏览器中显示如下:

新网址:https://api-storage-products.vercel.app/products?_page=2&_limit=12

获取网址:https://api-storage-products.vercel.app/products?_page=1&_limit=12

也就是说,它没有执行我想要的 url 的获取。

当我使用正常的获取时,它可以工作,但我无法缓存它,因为网址多次更改,它最终会生成将通过缓存解决的请求累积,这就是我使用react-query的原因,但是我在更新 fetchData 中的 url 时遇到问题。

next.js fetch rendering react-query
1个回答
0
投票

这是我的代码:

import React, { useState, useEffect } from 'react';
import { useQuery } from '@tanstack/react-query';
import { SearchParams } from '@/types/SearchParams';
import { useSearchParams } from 'next/navigation';

export default function useQueryProducts(params: SearchParams) {
  const searchParams = useSearchParams();

  const _page = searchParams.get('_page') || '1';
  const typeProduct = searchParams.get('typeProduct');
  const _sort = searchParams.get('_sort');
  const search_query = searchParams.get('search_query');
  const perPage = 12;
  const queryProduct = search_query?.replace(/\s+(?=\S)/g, '%20');

  const [quantity, setQuantity] = useState<null | number>(null);

  React.useEffect(() => {
    const fetchQuantity = async () => {
      let urlQuantity = 'https://api-storage-products.vercel.app/quantitys';

      if (search_query) {
        urlQuantity = `https://api-storage-products.vercel.app/products?q=${search_query.replace(
          /\s+(?=\S)/g,
          '%20',
        )}`;
      }
      try {
        const response = await fetch(urlQuantity);

        if (!response.ok) {
          throw new Error(`Erro ao buscar produtos: ${response.statusText}`);
        }
        const quantityData = await response.json();
        if (!search_query) {
          if (!typeProduct) {
            setQuantity(Number(quantityData.allProducts));
          }
          if (typeProduct === 'allProducts') {
            setQuantity(Number(quantityData.allProducts));
          }
          if (typeProduct === 'mensClothing') {
            setQuantity(Number(quantityData.mensClothing));
          }
          if (typeProduct === 'womansClothing') {
            setQuantity(Number(quantityData.womansClothing));
          }
        } else {
          setQuantity(quantityData.length);
        }
      } catch (error) {
        setQuantity(null);
      }
    };

    fetchQuantity();
  }, [search_query, typeProduct]);

  const baseUrl = 'https://api-storage-products.vercel.app/products';

  const [url, setUrl] = useState(
    new URL(`${baseUrl}?_page=${_page}&_limit=12`),
  );
  const fetchData = async () => {
    const response = await fetch(url.href);
    if (!response.ok) {
      throw new Error(`Erro ao buscar produtos: ${response.statusText}`);
    }

    console.log('url do fetch:', url.href);
    return response.json();
  };

  useEffect(() => {
    const newUrl = new URL(
      `https://api-storage-products.vercel.app/products?_page=${_page}&_limit=12`,
    );

    if (typeProduct && typeProduct !== 'allProducts') {
      newUrl.searchParams.append('category', typeProduct);
    }

    if (_sort) {
      let sortField = '';
      let order = '';

      if (_sort === 'news') {
        sortField = 'id';
        order = 'desc';
      } else if (_sort === 'LowerHigher') {
        sortField = 'price';
        order = 'asc';
      } else if (_sort === 'HigherLower') {
        sortField = 'price';
        order = 'desc';
      }

      if (sortField && order) {
        newUrl.searchParams.append('_sort', sortField);
        newUrl.searchParams.append('_order', order);
      }
    }

    if (queryProduct) {
      newUrl.searchParams.append('q', queryProduct);
    }

    console.log('newUrl:', newUrl.href);
    setUrl(newUrl);
  }, [_page, perPage, typeProduct, _sort, queryProduct]);

  const { isLoading, data, isError, refetch } = useQuery({
    queryKey: ['products', _page, perPage, queryProduct, _sort, typeProduct],
    queryFn: fetchData,
    staleTime: 1000 * 60 * 60 * 24,
  });

  return { isLoading, data, isError, refetch, quantity, perPage };
}
© www.soinside.com 2019 - 2024. All rights reserved.