Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

119
Vistas
UseEffect is thrown when it shouldn't be

I use a useEffect in my React code which works fine at first but writing a search engine using a useState called "search" when setting its new value through an input onChange my useEffect is executed automatically again although it is never waiting changing my useState to "search", this is my code

const [search, setSearch] = useState("");

useEffect(() => {
  pages();
}, [limitPage, page, products]);

const pages = () => {
  // eslint-disable-next-line
  getProducts(limitPage, page, search);
  getXlsProducts(100000, 1);
  const totalPages = Math.ceil(totalDocs / limitPage);
  const links = [];
  for (let i = 1; i <= totalPages; i++) {
    links[i] = i;
  }
  setNumbers(links);

  setTotalDocs(products.products?.totalDocs);
  setTotalPages(products.products?.totalPages);
  setCurrentPage(products.products?.page);
  setNextPage(products.products?.hasNextPage);
  setPreviousPage(products.products?.hasPrevPage);
};

I need to use the button that calls the handleSearch() function in order to perform the search, but as soon as a change in the input automatically occurs, my useEffect is executed:

<div>
  <input
    className="border-1 border-2 border-solid rounded border-slate-300"
    value={search}
    onChange={(e) => setSearch(e.target.value)}
  />
  <button onClick={() => handleSearch()}>
    <FiSearch />
  </button>
</div>

Here is the function to use when clicking on the button but it is never used because as soon as search changes value through the input it no longer gets executed:

const handleSearch = () => {
  setLimitPage(10);
  setPage(1);
  getProducts(limitPage, page, search);
};

How can I avoid the automatic firing of my useEffect so that I can use my search function through the button? thanks.

about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

useEffect(() => {
  pages();
}, [limitPage, page, products]);

Dependencies in React's hooks use shallow comparison.

As @ChrisG mentioned in the comment - "You have infinite loop". It's async loop because as you said, getProducts function request products from the server. So when you get a list of products from the server even if they semantically equal as already setted you still create a new array with new reference. So useEffect triggered again because reference on products list has changed!

//🥇triggered useEffect by first run
// when we create component and call `pages()`
useEffect(() => {
  pages();
}, [limitPage, page, products]);


const pages = () => {
  //🥈Make a request to the server and set products list
  // like setProducts(response.products) this cause
  // create new array with new reference
  getProducts(limitPage, page, search);
  ...
}

//🥉products === response.products // False because these are two diffirent objects
// so we trigger useEffect again (returns to 🥈)
useEffect(() => {
  pages();
}, [limitPage, page, products]);
about 4 years ago · Juan Pablo Isaza Denunciar

0

As far as I have understood , you want getProducts() to be called on the first render as well as whenever the state limitPage and page changes and whenever Search Button is pressed.

You already have handleSearch function for calling getProducts() that is triggering the API on the click of Search button,

const handleSearch = () => {
  setLimitPage(10);
  setPage(1);
   getProducts(limitPage, page, search);
};

In the handleSearch() as mentioned by @ChrisG in comment :- you need to take care of limitPage and page value as it will use the previous value here.

for calling API on first render and whenever the states limitPage and pagechanges, remove products dependency from useEffect and modify pages() function with the required statements:-

useEffect(() => {
   pages();
 }, [limitPage, page]);

const pages = () => {
  // eslint-disable-next-line
  getProducts(limitPage, page, search);
  getXlsProducts(100000, 1);
  const totalPages = Math.ceil(totalDocs / limitPage);
  const links = [];
  for (let i = 1; i <= totalPages; i++) {
  links[i] = i;
 }
  setNumbers(links);

};

I saw several states that you want to update on the change of products state, for that , you can have another useEffect with products dependency and a new method updating the required states:-

 useEffect(() => {
   updateStates();
 }, [products]);

const updateStates = () => {
  setTotalDocs(products.products?.totalDocs);
  setTotalPages(products.products?.totalPages);
  setCurrentPage(products.products?.page);
  setNextPage(products.products?.hasNextPage);
  setPreviousPage(products.products?.hasPrevPage);
 };
 
about 4 years ago · Juan Pablo Isaza Denunciar

0

The problem is the shallow comparison as stated by @maksimr. An alternative is to use class based components with shouldComponentUpdate:

shouldComponentUpdate(nextProps, nextState) {
    // if no products in current state, update when there are products in 
    // future state, or else remain.
    if(!this.state.products.length) {
        return nextState.products.length;
    }
    // update if there's a product in current state whose id
    // is not found in the next state's products
    return this.state.products.some((prod)=>(
        !nextState.products.find((p)=> (
            prod.id == p.id 
        )
    );
}
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda