'Replacing an entire array in state React Hooks - error Too many re-renders. React limits the number of renders to prevent an infinite loop
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.
Solution 1:[1]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | narF |
