How to pass argument to useSate's setState function?

97 Views Asked by At

I came across this codePen https://codepen.io/enmanuelduran/pen/LgMomz while learning react. I tried to make a few changes and ended up with "Too many re-renders" error.

Instead of

const handleClick = () => setCount(count + 1);

I tried to pass argument to the handleClick function

const handleClick = (x) => setCount(x + count + 1);

and in my return statement I changed

<button onClick={handleClick}>

i added

<button onClick={handleClick(1)}>

when I run it I get

Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
4

There are 4 best solutions below

5
On BEST ANSWER

Because here:

<button onClick={handleClick(1)}>

You are invoking handleClick immediately, not when the button is clicked, hence the function gets called on every render. This then triggers a re-render and you get your 'infinite' loop.


Try instead, an anonymous function that in turn calls your handleClick:

<button onClick={() => handleClick(1)}>

Or

<button onClick={e => handleClick(1)}>

If you need to utilise the event object, for example.


For what it's worth, the line that you had previously (<button onClick={handleClick}>) calls the handleClick function when the button is clicked, but passes the event object as the first argument.

0
On
<button onClick={handleClick}>

this code mean that onClick refer to handleChange method

while

<button onClick={handleClick(1)}>

mean that onClick is set to the returned value of handleClick


to fix the errors set the value ofonClick to function , like this

<button onClick={() => handleClick(1)}>
0
On

When you write handleClick(1) you are actually calling the function at that moment, which causes the function to re-call the render function and anyway to call the same function and so you enter an endless loop. To send the reference to a function (that is, the pointer), you have to write it like this:

<button onClick={() => handleClick(1)}>
0
On

Adding to all other answers, note that when your state depends on the previous state value, mostly in case of counters where you need to do some calculations based on the old value, say an increment, it is advised to use the callback inside the setFuntion which is returned from useState, so in your case,

The below code could sometimes produce incorrect results as you are directly setting the value taking the old value from the state, which can sometimes be a not updated value between renders,

const handleClick = () => setCount(count + 1);

So to make sure everything works well, use the callback way as below,

const handleClick = () => setCount( prevCount => prevCount + 1);

where the above callback receives an argument with the previos state value.