Learn how the “useState” hook in functional components can replace “this.setState” functionality for a React class component. This lesson will examine its syntax, usage, and it will also provide examples.
Table of Contents
What is it?
Start by looking at how the state is managed by using a class.
class App extends Component {
constructor(props) {
super(props);
this.state = {
items: []
};
}
setItems = items => {
this.setState(items);
}
render() {
// some code here
}
}
Here this.state
is being used to initialize items and this.setState
is used to update the state.
With useState
hook, replace this.state
and this.setState
with a single hook call. The above example will reflect this when using the useState
hook to manage items.
const App = () => {
const [items, setItems] = useState([]);
return (
// some code
);
};
As seen by the example, the useState
hook initializes the state and provides a callback to update the state in a single line of code.
When do we use it?
Anytime a functional component needs to hold the internal state, use the useState
hook to remember the state. In other words, create stateful logic by using the useState
hook.
Syntax
const [state, setState] = useState(INITIAL_STATE);
The useState
hook only takes one argument which is the value of the initial state.
It returns an array with two items in it:
- The first item in this array is a variable that holds the current value of the state.
- The second item is a function for updating the state variable with the new value.
“Array Destructuring” syntax from ES6 is being used to assign the array items to state and setState
variables. In theory, it is possible to do this to achieve the same result:
const stateArray = useState(INITIAL_STATE);
const state = stateArray[0];
const setState = stateArray[1];
However, it is recommended to use ES6 syntax because it is much easier to read and a wider community is using useState
hook in this way.
Usage
Build a basic counter example with the useState
hook.
Every time someone clicks the “Click me” button, increment the counter by 1. This is possible by managing the count state in this component.
On line #6, state should be set up with the useState
hook.
On line #13, an onClick
handler to the button has been provided. This function calls setCount
with the new count on every click. Everything else is left to the React library to update the state for the count.
Run the application to see it in action.
Managing state for multiple values
In many cases, a component requires an internal state for more than one value. A typical example is a component with form elements in it.
Begin by examining a class component with two input fields for name
and email
in it. Set the initial values in the constructor. Later, you will rely on this.setState
to safely merge state updates.
class App extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
email: ''
};
}
setName = name => {
this.setState({ name });
}
setEmail = email => {
this.setState({ email });
}
render() {
return (
<React.Fragment>
<input value={this.state.name} onChange={event => this.setName(event.target.value)} />
<input value={this.state.email} onChange={event => this.setName(event.target.value)} />
</React.Fragment>
)
}
}
Now, try to convert the same example to use hooks.
With the useState
hook, you do not need to combine two different values in one state variable. Instead, define as many state variables as required by calling the useState
hook. Behind the scenes, React Fiber keeps track of each call to useState
separately.
The example above will look like the code snippet below by using the useState
hook. You will appreciate that it is a much cleaner way to manage state by using a hook.
const App = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
return (
<React.Fragment>
<input value={name} onChange={event => setName(event.target.value)} />
<input value={email} onChange={event => setEmail(event.target.value)} />
</React.Fragment>
);
};