I have a problem with using my custom hook after using a useQuery hook.
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();
const productData = useProductData(products);
if (isLoading) return <Spinner />;
return (
<Box>
<ProductPage productData={productData} />
</Box>
);
};
export default Catalogue;
So, i want my useProductData execute only if have already got products from useBeers.
useBeers.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;
useProductData.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;
I tried changing the order of lines to execute useProductData only if !isLoading like this but it didn`t work as i expected, i had an error:
React Hook "useProductData" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return?
const { data: products, isLoading } = useBeers();
if (isLoading) return <Spinner />;
const productData = useProductData(products);
2
Answers
To resolve this issue, ensure that your hooks are called unconditionally, meaning they’re called in the same order and at the top level of your functional component.
Try like this :
Why not
with a bit of a cleanup ofc, but that’s the gist of it