I met react-hooks/exhaustive-deps
lint error warning. Here is my code
const fetchData = async pageNumber => {
if (pageNumber > totalPages) {
return;
}
try {
setIsLoading(true);
// ... call api
const content = response.data.content;
if (pageNumber === 1) {
setTotalPages(response.data.totalPages);
setActivityData(content);
} else {
setActivityData([...activityData, ...content]);
}
setCurrPage(currPage + 1);
} catch (e) {
console.log(e);
} finally {
// ...
}
};
useEffect(() => {
fetchData(currPage);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currPage]);
useEffect(() => {
setCurrPage(1);
setActivityData([]);
setTotalPages(1);
}, [activityStatus]);
These functions are designed to display the activityData
paginatedly.
If I put fetchData in dependencies, it will raise another error saying this function will re-render. I’ve seen other posts suggesting putting fetchData inside useEffect, but I can’t do it in my code.
- What’s wrong with my way of using useEffect?
- Is there a better way to manage pagination and display it in a flow?
2
Answers
I used to put the
// eslint-disable-next-line react-hooks/exhaustive-deps
everywhere, but now I know that it’s not (always) the case.When I see an EsLint error complaining about something, usually I turn on my brain and I’m thinking: "How can I do it better in order to remove this problem?"
In your case, you have a
useEffect
that triggers whencurrPage
changes. This is causing the loading to become true, gets the content and update the page number. Let’s try to refactor it, separating all the things into two important steps:I’ll answer your question 1 – question 2 is more opinion-based and more appropriate for a different Stack Exchange (like Code Review).
TL;DR: wrap your function in useCallback.
When you define a function in the body of a component, it will get recreated every time the component is computed for possible re-rendering. For many functions, that’s fine; the cost of recreating the function is minimal.
However, everything changes once an effect depends on that function. Since the function is recreated, it fails a referential equality check. This causes the infinite loop:
This is why useCallback exists. It caches the defined function so that it will only be recreated if one of its dependencies changes. This means the function passes the equality check and won’t cause the effect to fire again.
In your code this would look something like: