skip to Main Content

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

  • item, which filter the products that correspond to that
  • category. Then, I add them in const called newFilteredProducts. Everything up until here works fine, however, in order to update the rendered items with the filtered ones and display them, I need to call Products(false, newFilteredProducts).

    When I try to do that, I get the following error: enter image description here

    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


    1. "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 function filterProductList. 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:

      1. In your FilterMenu component, maintain state for filtered products and pass them as props to Products.
      2. Modify the Products component to receive the filtered products as props and render them accordingly.

      Here’s the modified code:

      import React, { useState, useEffect } from 'react';
      
      function FilterMenu({ products, setFilteredProducts }) {
          // Function to filter products by category
          const filterProductList = (category) => {
              const newFilteredProducts = products.filter(product => product.category.includes(category));
              setFilteredProducts(newFilteredProducts);
          };
      
          return (
              <div className="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 className="SearchIcon" src={searchIcon} />
                      </div>
                  </ul>
              </div>
          );
      }
      
      function Products({ products }) {
          const items = products.map((product, index) => (
              <div className ="grid-item" key={index + 1}>
                  <div className="picture">
                      <img className="productPicture" src={'data:image/jpeg;base64,' + product.imageData} />
                  </div>
                  <div className="title"><a>{product.name} {product.weight}гр</a></div>
                  <div className="price"><a>{product.price} лв.</a></div>
                  <div className="cartImage">
                      <img className="cart" src={cartImage} />
                  </div>
              </div>
          ));
      
          return (
              <div className="grid-container">
                  {items}
              </div>
          );
      }
      
      function App() {
          const [products, setProducts] = useState([]);
          const [filteredProducts, setFilteredProducts] = useState([]);
      
          useEffect(() => {
              const url = "http://localhost:5104/Product";
              fetch(url)
                  .then((response) => response.json())
                  .then((data) => setProducts(data));
          }, []);
      
          return (
              <div>
                  <FilterMenu products={products} setFilteredProducts={setFilteredProducts} />
                  <Products products={filteredProducts.length ? filteredProducts : products} />
              </div>
          );
      }
      
      ReactDOM.render(<App />, document.getElementById('root'));
      
      
      Login or Signup to reply.
    2. There are multiple issues:

      You haven’t imported the hooks. Add useState and useEffect to your import statement from ‘react’:

      import React, { useState, useEffect } 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 component

      Move 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.

      Login or Signup to reply.
    Please signup or login to give your own answer.
    Back To Top
    Search