When creating a React app, we'll almost always need a way to store / manage state within our component(s) — the useState React Hook allows us to do this in a cleaner and more concise way.
Before Hooks
Prior to React Hooks — like useState — the way we created/managed state in React was through class components, which looked like this:
class Example extends React.Component {
constructor(props) {
super(props);
// creating our state object here
this.state = {
count: 0
};
// -- We access count below via 'this.state.count' --
// -- We update/change count via 'this.setState' --
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click Me
</button>
</div>
);
}
}
After React Hooks
With the introduction of React Hooks we no longer need to go about creating/managing state this way — we can use functional components and the useState React Hook.
Note: Hooks will not work in Class Components
There is nothing particularly special about useState, at the end of the day all we are doing is the following:
- Importing useState from React
- Destructuring useState — first item will be the name of our state variable, second item will be the name of the function that we use to update our state variable. We can name these whatever we want.
- Give our state an initial value by passing it to useState
Here is how we'd recreate the above code using functional components + React Hook useState:
// 1. Importing useState
import React, { useState } from 'react'
function App() {
// 2. Destructuring useState
// naming our: state variable 'count' & update function 'setCount'
let [count, setCount] = useState(0);
// 3. useState allows us to pass in the starting value, here it is 0
// below we are:
// - displaying count with {count}
// - updating count with setCount when the button is clicked (more info below code)
return (
<div className="App">
<p>You clicked {count} times</p>
<button onClick={() => setCount(prevCount => prevCount + 1)}>
Click Me
</button>
</div>
);
}
export default App;
At times, React will "batch" state updates to improve performance, because of this it is not ideal to simply update state like so:
<button onClick={() => setCount(count++}>
Click Me
</button>
If React "batches" the state update and your button onClick looks like the above code — it is possible that the state won't be updated with the correct value. The workaround to this is to do what was done in the recreation code snippet:
<button onClick={() => setCount(prevCount => prevCount + 1)}>
Click Me
</button>
Whats happening here:
- When the button is clicked, the setCount updater function is called, but instead of passing it a value (like 'count++'), we're passing it a function.
- The function is passed an argument 'prevCount' that always refers to the previous value of our state variable (this can be called whatever you want)
- The function then makes use of 'prevCount' to ensure that we are always updating the correct value and also prevents React from "batching" the updates.
It is easier to see the difference between using 'count++' and 'prevCount ⇒ prevCount + 1' by trying it out yourself. Head over to the replit and quickly click on the button — with 'count++' you'll notice that it will not register every single click if you're clicking fast enough, however with 'prevCount ⇒ prevCount + 1' you'll notice that every single click is registered — and thus your count will always be correct.
As always, refer to the docs for more info:
State Hook
Feel free to reach out on any of my socials for questions, feedback, or just to connect / say hello 👋.
Top comments (2)
setCount(prevCount => prevCount + 1)
our state is count how we are updating its value. Actually how the setCount is returning the updated value to count in the below code
You clicked **{count}** times
Excellent, short description!