Why can't the dispatch function of a useState hook be passed directly into an onClick handler?

695 views Asked by At
const Counter = () => {
  const [count, setCount] = useState(0);
  // return <button onClick={setCount(count + 1)}>{count}</button>;
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
};

I'm aware that the commented out line causes an infinite loop but I want to know why that's the case. Isn't the setCount dispatch function invoked only on click?

2

There are 2 answers

0
T.J. Crowder On BEST ANSWER

It's because the expression within a {} in JSX is evaluated and then its result is used where that {} was — in this case, as the value of the onClick property. So onClick={setCount(count + 1)} evaluates setCount(count + 1) (calling the function, which will set the state) and then uses the resulting value for the onClick. Since calling it sets the state, that causes re-rendering, which does it again endlessly.

Your other version creates a function when the JSX is evaluated without calling it, which is why it works.

1
arieljuod On

when you do this:

onClick={setCount(count + 1)}

you are calling that method during render.

I don't see the infinite loop, but you are calling that setCount for each render causing a re render.