You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让自定义Hook依赖React Query的useQuery Hook执行?

解决React Hook条件调用错误的方案

问题原因

React Hook的核心规则要求:所有Hook必须在组件的顶层作用域调用,不能放在条件判断、循环或嵌套函数中。你尝试把useProductData放在isLoading判断之后,属于条件调用,违反了Hook的调用顺序规则,因此触发报错。

解决方案:让Hook兼容未加载状态

修改useProductData,使其能够处理products为undefined的情况,这样就可以在组件顶层安全调用该Hook,无需条件判断。

修改后的useProductData.js

import { useState } from "react";

function useProductData(products) {
  // 当products未加载完成时,返回默认结构避免报错
  if (!products) {
    return {
      filteredValues: [],
      checkedBrands: {},
      products: [],
      title: "Crowlers",
      brandFilterData: { 
        uniqueBrands: [], 
        checkedBrands: {}, 
        setCheckedBrands: () => {} 
      },
      priceFilterData: { 
        min: 0, 
        max: 0, 
        filteredValues: [], 
        setFilteredValues: () => {} 
      },
      isVoucher: false
    };
  }

  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;

保持Catalogue.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();

  // 顶层调用Hook,完全符合React规则
  const productData = useProductData(products);

  if (isLoading) return <Spinner />;

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

export default Catalogue;

原理说明

通过在useProductData中提前判断products是否存在,当数据未加载时返回安全的默认值,既保证了Hook始终在组件顶层调用,又避免了执行map、Math.min等依赖products存在的代码而导致的报错。当isLoading结束后,products数据就绪,Hook会自动返回正确的计算结果。

内容的提问来源于stack exchange,提问作者ivsheva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:06:20