Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

115
Views
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 answers
Answer question

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!