search

Home  >  Q&A  >  body text

What's the point of react-hooks/exhaustive-deps warning for state setter?

<p>I'm building pagination using React. </p> <p>The application uses state to manage paging and search. I want to reset the pagination to page 1 when the search term changes. </p> <pre class="brush:php;toolbar:false;">// Simplified example function useSearchTerm() { return React.useState(""); } function usePage() { return React.useState(1); } function MyComponent(){ const [searchTerm, setSearchTerm] = useSearchTerm() const [page, setPage] = usePage(); useEffect(() => { setPage(1); }, [searchTerm]); // <-- Here is the ESLint warning }</pre> <p>This gives me an ESLint warning <code>React Hook useEffect missing dependency: 'setPage'. Either include it or remove the dependency on useEffect hook array.eslintreact-hooks/exhaustive-deps. </p> <p>But of course, if I include setPage in the dependency, the effect will be called every time I render. </p> <p>Am I doing something wrong with this use case? </p>
P粉465287592P粉465287592453 days ago602

reply all(1)I'll reply

  • P粉156983446

    P粉1569834462023-09-02 00:17:20

    This intermediate function seems to be the problem:

    function usePage() {
      return React.useState(1);
    }

    The state setting function returned by useState itself is not recreated on each render, but calling it via this external function seems to break that. This causes the dependencies to change, as observed in the useEffect dependencies array.

    If you don't need this usePage function (in the example you don't, but there may be cases where it makes sense in a larger context), then just remove it entirely and use it directly useState

    const [page, setPage] = useState("");

    Generally, one doesn't want to call hooks inside a function anyway, as it can quickly and easily lead to violating the rule that hooks must be called consistently and in the same order on every render. Therefore, it's best to keep hook calls in the body of the component itself (and early in the component's logic).

    Sometimes, there are situations where you really want a custom function to act as a dependency in useEffect. Since the declared function is redeclared on every render, you have the problem you encountered above. To solve this problem, you can wrap the function in a useCallback hook, which itself also has a dependency array, very similar to useEffect. The purpose of this hook is to create custom functions that React can cache as a single function instance across renders (unless dependencies change). For example:

    const myCustomFunction = useCallback(args => {
      // use function args, etc.
    }, [someDependencies]);

    reply
    0
  • Cancelreply