Home > Net >  Replacing an entire array in state React Hooks - error Too many re-renders. React limits the number
Replacing an entire array in state React Hooks - error Too many re-renders. React limits the number

Time:03-14

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.

CodePudding user response:

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.

  • Related