This code is in the same file (index.js). I am genuinely new into web development and it seems I messed up with the code and I noticed it after I was done with the front-end build, after I added the api.
import React from 'react';
import ReactDOM from 'react-dom/client';
function FilterMenu(props){
const [filteredProducts, setFilteredProducts] = useState([]);
// Function to filter products by category
const filterProductList = (category) => {
const newFilteredProducts = products.filter(product => product.category.includes(category));
setFilteredProducts(newFilteredProducts);
console.log(newFilteredProducts);
{Products (false, newFilteredProducts)} //(THE PROBLEMATIC LINE OF CODE)
};
return (
<div class="filterMenu">
<ul>
<li><a>...</a></li>
<li><a>ВСИЧКИ</a></li>
<li><a onClick={() => filterProductList('Гривни')}>ГРИВНИ</a></li>
<li><a>ОГЪРЛИЦИ</a></li>
<li><a>ПРЪСТЕНИ</a></li>
<li><a>ОБЕЦИ</a></li>
<div className='filterSearchbar' id="filterSearchbar" >
<input type="text" className='filterText' id="filterText"/>
<img class="SearchIcon" src={searchIcon} />
</div>
</ul>
</div>
)
}
function Products(start, listOfFilteredProducts) {
console.log(start);
const [listOfProducts, setListOfProducts] = useState([]);
function FetchData() {
useEffect(() => {
const url = "http://localhost:5104/Product";
fetch(url)
.then((response) => response.json())
.then((data) => {
for (let i = 0; i < data.length; i++) {
products.push(data[i]);
}
console.log(products);
setListOfProducts(products);
})
}, [])
}
if (start)
{
console.log(start);
FetchData();
}
else {
setListOfProducts(listOfFilteredProducts);
console.log(listOfFilteredProducts);
}
console.log(listOfFilteredProducts);
const items = [];
for (let i = 0; i < listOfProducts.length; i++)
{
items.push(
<div className ="grid-item" key={i+1}>
<div className="picture">
<img class="productPicture" src={'data:image/jpeg;base64,' + products[i].imageData} />
</div>
<div className="title"><a>{products[i].name} {products[i].weight}гр</a></div>
<div className="price"><a>{products[i].price} лв.</a></div>
<div className="cartImage">
<img class="cart" src={cartImage} />
</div>
</div>
);
}
return (
<div className="grid-container">
{items}
</div>
)
}
const filterMenu = ReactDOM.createRoot(document.getElementById('filterMenu'));
const productsDisplay = ReactDOM.createRoot(document.getElementById('products'));
filterMenu.render(
<FilterMenu />
)
productsDisplay.render (
<Products true />
)
Currently what the code does: Products is rendered on refresh by giving true value to the prop ‘start’. After the data is collected, it creates a product with the product’s data, adding it to the array items[]. Items[] is used to render the products on the page.
FilterMenu is used to build a menu I have on the page with an onClick event for each
When I try to do that, I get the following error:
I am stuck on this problem and couldn’t figure out how to fix the issue. I tried to add a parent function, but then I can’t call in the productsDisplay.render part of the code. Basically, my approach has to be changed but my inexperience makes it difficult for me to understand how the code needs to be updated or if there is a way to export the Products function within the same file.
2
Answers
"Invalid hook call," typically occurs when you’re trying to use React hooks (like useState and useEffect) in a function/component where they’re not supposed to be used directly.
In your case, you’re trying to call a component
Products
with the useState hook from within another functionfilterProductList
. You cannot directly call a component with hooks like this.Instead, you should redesign your component structure to pass the filtered products as props to the
Products
component. Here’s how you can do it:Here’s the modified code:
There are multiple issues:
You haven’t imported the hooks. Add
useState
anduseEffect
to your import statement from ‘react’:Replace
{Products (false, newFilteredProducts)}
with JSX<Products start={false} filteredProducts={newFilteredProducts} />
and move it into the render method or return statement of a componentMove the product list state to a common parent component so that FilterMenu can set the filtered products and Products can consume them.
Change
<Products true />
to<Products start={true} />
to pass a boolean correctly.You also need to avoid direct DOM manipulation. Use state and props to handle dynamic changes instead of direct calls to render with ReactDOM.
Use
useEffect
Correctly. The FetchData function inside Products should not be a nested function. Place your fetch call directly in the useEffect hook.