0

I have an array of items stored in state and rendered when the component loads. I'm attempting to replace this array with a filtered array but I'm getting the error:

Too many re-renders. React limits the number of renders to prevent an infinite loop. 

Here's the code:


let filteredItemsArray: IListItems[] = [];

 if (searchInputTitle.length > 0) { //This is if it's filtered or not:
        filtered = !searchInputTitle ? requests : requests.filter((title) => title.Title.toLowerCase().includes(searchInputTitle.toLowerCase()));
        setFilteredItemsArrayState(filtered);
    } else {
        let sortedByID: IListItems[] = requests.sort((a, b) => a.Id > b.Id ? 1 : -1);
        filteredItemsArray = sortedByID;
        setFilteredItemsArrayState(filteredItemsArrayState => [...filteredItemsArrayState, ...filteredItemsArray]);
    }

///Render:

  <DetailsList className={styles.DetailsList}
       items={filteredItemsArrayState.slice((ListPage - 1) * 50, ((ListPage * 50)))}
      />

As you can see I'm attempting to use spread operators to replace the old array with the new, but it's not working.

Notes: I removed the .slice to see if that's causing the issue but it's not.

NightTom
  • 418
  • 15
  • 37
  • Does this answer your question? [Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop](https://stackoverflow.com/questions/55265604/uncaught-invariant-violation-too-many-re-renders-react-limits-the-number-of-re) – Emma Mar 14 '22 at 11:25

1 Answers1

0

You need to wrap this code into a useEffect function:

if (searchInputTitle.length > 0) { //This is if it's filtered or not:
        filtered = !searchInputTitle ? requests : requests.filter((title) => title.Title.toLowerCase().includes(searchInputTitle.toLowerCase()));
        setFilteredItemsArrayState(filtered);
    } else {
        let sortedByID: IListItems[] = requests.sort((a, b) => a.Id > b.Id ? 1 : -1);
        filteredItemsArray = sortedByID;
        setFilteredItemsArrayState(filteredItemsArrayState => [...filteredItemsArrayState, ...filteredItemsArray]);
    }

With the code you have, every time the page render, it will execute the if-else statement and update the state so this mean, the page will re-render constantly.

The solution:

useEffect(() => {
if (searchInputTitle.length > 0) { //This is if it's filtered or not:
        filtered = !searchInputTitle ? requests : requests.filter((title) => title.Title.toLowerCase().includes(searchInputTitle.toLowerCase()));
        setFilteredItemsArrayState(filtered);
    } else {
        let sortedByID: IListItems[] = requests.sort((a, b) => a.Id > b.Id ? 1 : -1);
        filteredItemsArray = sortedByID;
        setFilteredItemsArrayState(filteredItemsArrayState => [...filteredItemsArrayState, ...filteredItemsArray]);
    }
}, [searchInputTitle])

With the solution, the function only get executed when searchInputTitle change and not every time.

narF
  • 70
  • 4
  • That's made the error go away but it's now rendering twice in the list (duplicating the 4 items so there are 8)! What about putting the if/else into a function triggered on change?? – NightTom Mar 14 '22 at 11:31
  • 1
    I think you can solve your problem easily just creating an array every time you request the data, not merging like you are doing now. – narF Mar 14 '22 at 11:35
  • If it helps anyone, I moved the if/else with the state setters into a function (not using useeffect at all) and this solved the issue and was tidier and easier to maintain. – NightTom Mar 14 '22 at 11:46