React useState hook feature that is often missed

The set function of useState hook can take a callback as an argument.

setCount(count => count + 1);

Common use of the state hook is:

const Counter = () => {
const [count, setCount] = useState(0);

return (
<button onClick={() => setCount(count + 1)}>
Increment
</button>
);
};

From a performance standpoint, it is good to wrap all callbacks with useCallback hook:

const Counter = () => {
const [count, setCount] = useState(0);
const increment = useCallback(() => setCount(count + 1), [count])
return (
<button onClick={increment}>
Increment
</button>
);
};

The increment function will be created each time the count value changes. In this case, using useCallback doesn’t make much sense.

This can be fixed by passing a function to setCount which takes the current value.

const Counter = () => {
const [count, setCount] = useState(0);
const increment = useCallback(() => setState(count => count + 1), []);
return (
<button onClick={increment}>
Increment
</button>
);
}

Now the function has no dependencies. It will only be created once on the first render.

As a small reminder, the original value can also be initialized using a function in case it is non-trivial.

const [count, setCount] = useState(() => getCount(props));

Do you know why React hooks cannot be called in conditions? :-)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store