1

I have read that the rules for using React's hooks are:

Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns. It’s not supported to call Hooks (functions starting with use) in any other cases, for example:

  • 🔴 Do not call Hooks inside conditions or loops.
  • 🔴 Do not call Hooks after a conditional return statement.
  • 🔴 Do not call Hooks in event handlers.
  • 🔴 Do not call Hooks in class components.
  • 🔴 Do not call Hooks inside functions passed to useMemo, useReducer, or useEffect.

See rules

Yet React documentation shows an example where they call setCount inside an onClick button function (handleClick). Isn't the function handleClick called by onClick an event handler? And further more doesn't this example violate the rule that it must be called in the top-level? I must be missing something obvious.

How do I create a handleClick using setCount so as to not violate React's hook rules?

Here is the code from the React documentation:

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You pressed me {count} times
    </button>
  );
}
1
  • Sorry that I missed this in the documentation. Thanks for the clarification. Commented Apr 4 at 19:58

1 Answer 1

1

Isn't the function handleClick called by onClick an event handler?

Yes, handleClick is the onClick event handler.

doesn't this example violate the rule that it must be called in the top-level?

No, event handlers are not React hooks, so the Rules of Hooks do not apply to them.

How do I create a handleClick using setCount so as to not violate React's hook rules?

Neither handleClick nor setCount are React hooks, so there are no special rules attached to when and where these functions can be called. Note that in that example the useState hook is called at the top-level in the component function body and follows the Rules of Hooks.

Just an additional side-note since it seems you are just starting in React, incrementing a count is the classic example where you would want to use a functional state update to correctly update from the current state. Pass a callback function to the setCount state updater function that is passed the current state value from which you can compute the next state value.

setCount(currentCount => currentCount + 1); // *

This avoids issues of stale Javascript Closures in callback function scopes and similar issues that can arise when passing these callback functions down to children components as props.

*Note: Named the current state value currentCount but you can use any valid Javascript identifier. Convention is to use the same state name, i.e. setCount(count => count + 1) or sometimes abbreviated to setCount(c => c + 1) if the code is trivial enough to follow.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.