Better way to write useState 👌 — React Hooks

Sai Kiran
3 min readMar 7, 2023

--

You must have already know that react hooks are introduced in version 16.8. So let’s talk about one of the hook useState.

useState

This hook allows functional component to access the local state and re-renders the component whenever the state value is changed. React preserves the state for each render so that you won’t lose the previous state.

Following is the basic way of using useState in react where there is no computation logic required based on the previous value.


//javascript way of incrementing
function UseStateExample(){
let counter = 0

const incrementByOne = ()=> {
counter++

// Doing this way. React doesn't re-render the component. So, value is not updated in the UI
}
}

//React way of rendering the component
function UseStateExample(){
const [counter, setCounter] = useState(0)

const incrementByOne = ()=> {
setCounter(counter+1)

//Not only renders the component but also value is updated in the UI
}
}

export default UseStateExample;

Above listed example is straight forward. So, let’s create a hypothetical scenario where you want to compute value based on the current value.

Example -2 👇

Here, we want to increment the counter by 2 but to show the gotcha of react while updating the state, we call the setCounter() twice in the same function and see what happens.


export default function UseStateExample(){

const [count, setCount] = useState(10)

const incrementByOne = () => {
setCount(count + 1) // 10 + 1 =11
setCount(count + 1) // 10 + 1 =11
}
return (
<button onClick={() => incrementByOne}>
Increment
</button>
);
}
export default UseStateExample;

if you have ran the same code in your local, you will observe that state is not incrementing twice as written in the code but incremented by one.

Now, why is this happening? because of Batching.

React automatically groups all the multiple state updates into a single for the better performance — Automatic Batching

How are we gonna deal with it now?

Following is the way:👇

export default function UseStateExample(){

const [count, setCount] = useState(10)

const incrementByOne = () => {
setCount(currentCount => currentCount + 1) // 10 + 1 =11
setCount(currentCount => currentCount + 1) // 11 + 1 =12
}

return (
<button onClick={() => incrementByOne}>
Increment
</button>
);
}
export default UseStateExample;

Instead of mutating the value directly and calling the setter, just use the arrow function to access current value and increment it. It would be nice way of computing a value based on the current state.

--

--

Sai Kiran

Web Developer | javascript | react | vue | blockchain enthusiast | Lunar enthusiast