Llamada de gancho no válida cuando intento llamar a una función en otra función Reaccionar

Resuelto Руслан Василев asked hace 7 meses • 2 respuestas

Este código está en el mismo archivo (index.js). Soy realmente nuevo en el desarrollo web y parece que me equivoqué con el código y lo noté después de terminar con la compilación del front-end, después de agregar la 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 />
)

Actualmente, lo que hace el código: los productos se representan al actualizar dando un valor real al accesorio 'inicio'. Una vez recopilados los datos, crea un producto con los datos del producto y lo agrega a la matriz items[]. Items[] se utiliza para representar los productos en la página.

FilterMenu se usa para crear un menú que tengo en la página con un evento onClick para cada uno

  • item, que filtra los productos que corresponden a ese
  • categoría. Luego, los agrego en una constante llamada newFilteredProducts. Todo hasta aquí funciona bien, sin embargo, para actualizar los elementos renderizados con los filtrados y mostrarlos, necesito llamar a Products(false, newFilteredProducts).

    Cuando intento hacer eso, aparece el siguiente error:ingrese la descripción de la imagen aquí

    Estoy atascado en este problema y no sé cómo solucionarlo. Intenté agregar una función principal, pero no puedo llamar a la parte del código ProductsDisplay.render. Básicamente, mi enfoque debe cambiarse, pero mi inexperiencia me dificulta entender cómo se debe actualizar el código o si hay una manera de exportar la función Productos dentro del mismo archivo.

  • Aceptado

    La "llamada de gancho no válida" generalmente ocurre cuando intentas usar ganchos de React (como useState y useEffect) en una función/componente donde se supone que no deben usarse directamente.

    En su caso, está intentando llamar a un componente Productscon el gancho useState desde otra función filterProductList. No puedes llamar directamente a un componente con ganchos como este.

    En su lugar, debe rediseñar la estructura de su componente para pasar los productos filtrados como accesorios del Productscomponente. Así es como puedes hacerlo:

    1. En su componente FilterMenu, mantenga el estado de los productos filtrados y páselos como accesorios a Productos.
    2. Modifique el componente Productos para recibir los productos filtrados como accesorios y renderizarlos en consecuencia.

    Aquí está el código modificado:

    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'));
    
    
    Nijat Mursali avatar Feb 16 '2024 16:02 Nijat Mursali

    Hay varios problemas:

    No has importado los ganchos. Agregue useStatey useEffecta su declaración de importación desde 'react':

    import React, { useState, useEffect } from 'react';
    

    Reemplazar {Products (false, newFilteredProducts)}con JSX <Products start={false} filteredProducts={newFilteredProducts} />y moverlo al método de renderizado o declaración de retorno de un componente

    Mueva el estado de la lista de productos a un componente principal común para que FilterMenu pueda configurar los productos filtrados y los Productos puedan consumirlos.

    Cambie <Products true />a <Products start={true} />para pasar un booleano correctamente.

    También debes evitar la manipulación directa del DOM. Utilice estado y accesorios para manejar cambios dinámicos en lugar de llamadas directas para renderizar con ReactDOM.

    Usar useEffectcorrectamente. La función FetchData dentro de Productos no debe ser una función anidada. Coloque su llamada de recuperación directamente en el gancho useEffect.

    Manters avatar Feb 16 '2024 16:02 Manters