使自定义钩子依赖于React Query钩子

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

在使用 useQuery 挂钩后,我在使用自定义挂钩时遇到问题。

目录.jsx

import { Box, Spinner } from "@chakra-ui/react";
import ProductPage from "../../components/Products/ProductPage";
import useBeers from "../../hooks/useBeers";
import useProductData from "../../hooks/useProductData";

const Catalogue = () => {
  const { data: products, isLoading } = useBeers();

  const productData = useProductData(products);

  if (isLoading) return <Spinner />;

  return (
    <Box>
      <ProductPage productData={productData} />
    </Box>
  );
};

export default Catalogue;

所以,我希望我的 useProductData 仅当已经从 useBeers 获取产品时才执行。 使用Beers.js

import { useQuery } from "@tanstack/react-query";
import axios from "axios";

const useBeers = () =>
  useQuery({
    queryKey: ["beer"],
    queryFn: () =>
      axios.get("localhost:3001/api/beers").then((response) => response.data),
  });

export default useBeers;

使用ProductData.js

import { useState } from "react";

function useProductData(products) {
  const brands = products.map(({ id, brand }) => ({
    id,
    brand,
  }));
  const prices = products.map((item) => item.price);
  const min = Math.min(...prices);
  const max = Math.max(...prices);

  const title = "Crowlers"; // TODO

  const uniqueBrands = brands.filter(
    (item, index, self) =>
      index === self.findIndex((t) => t.brand === item.brand)
  );

  const [filteredValues, setFilteredValues] = useState([min, max]);
  const [checkedBrands, setCheckedBrands] = useState({});

  const brandFilterData = { uniqueBrands, checkedBrands, setCheckedBrands };
  const priceFilterData = { min, max, filteredValues, setFilteredValues };

  const isVoucher = products.every((product) =>
    product.name.includes("Voucher")
  );

  return {
    filteredValues,
    checkedBrands,
    products,
    title,
    brandFilterData,
    priceFilterData,
    isVoucher,
  };
}

export default useProductData;

我尝试仅在 !isLoading 像这样的情况下更改执行 useProductData 的行顺序,但它没有按我的预期工作,我遇到了错误: React Hook“useProductData”被有条件地调用。 React Hooks 必须在每个组件渲染中以完全相同的顺序调用。您是否在提前返回后不小心调用了 React Hook?

const { data: products, isLoading } = useBeers();

  if (isLoading) return <Spinner />;

  const productData = useProductData(products);
javascript reactjs hook react-query tanstackreact-query
1个回答
-1
投票

要解决此问题,请确保无条件调用您的钩子,这意味着它们以相同的顺序并在功能组件的顶层调用。 尝试这样:

import { Box, Spinner } from "@chakra-ui/react";
import ProductPage from "../../components/Products/ProductPage";
import useBeers from "../../hooks/useBeers";
import useProductData from "../../hooks/useProductData";

const Catalogue = () => {
  const { data: products, isLoading } = useBeers();

  if (isLoading) return <Spinner />;

  // Move useProductData inside the component body
  const productData = useProductData(products);

  return (
    <Box>
      {products && <ProductPage productData={productData} />}
    </Box>
  );
};

export default Catalogue;
© www.soinside.com 2019 - 2024. All rights reserved.