Tech: React Hooks - “State” Of The Art…
Giving React components a “State” is the most popular way to store program data in parent components that child components might need for themselves or to share with other children so they can do their jobs. Up until recently the only way to give a component a state was to declare it as a Class Component, which is a bit messier and more involved than the Functional Component, which is what everyone likes. But then, a little less than a year ago the boffins at React released v16.8, which introduced the concept of “Hooks” that let you use state and other features previously confined to class components, inside functional components.
(Note: there are actually lots of special rules that govern where you can and can’t use hooks, but they are beyond the scope of this post. If you want to learn more about the “Rules of Hooks” check out “https://reactjs.org/docs/hooks-rules.html”.)
Lets start with a simple example of a “click-counter” written as a traditional class component:
class Example extends React.Component {
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
Here we initialize the state with a “count” of 0, and then every time there is a button click-event the callback function uses setState
to update the count by one. Because it’s a class component, we can use this.
to refer to the component’s own state.
But functional components don’t have a notion of this.
! This is where hooks come in; in order to make them self-referential we have to import a hook called useState.
import React, { useState } from 'react';
function Example() {
// ...
}
The reason useState
was invented was because coders were writing their components as functions, only to find out at some point in the future they would need to add state to them. This meant having to re-write the entire component as a class. Now with useState
the designer can add state directly to the function, no major re-write needed.
Instead of using this.state
, we add state to the function with the useState
hook:
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0);// Array Destructuring, yeet!
In this example we are declaring a variable called count
and using useState
to make it a “state variable”. The value inside the ()
sets the initial state to ‘0’. The function returns two values, the current state and the function that updates it (setCount):
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
Notice that now, instead of having to call this.state.count
to access the count state, we can just use the nice clean count
variable:
<p>You clicked {count} times</p>
Instead of:
<p>You clicked {this.state.count} times</p>
And to update the state, this:
<button onClick={() => setCount(count + 1)}> Click me
</button>
Instead of:
<button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me
</button>
As always, whether and where you might choose to use Functional + useState vs. Class + State is a matter of personal choice, and as I mentioned hooks have some limitations as to where they can be used. But IMHO, Functions with Hooks is a lot less typing and looks a lot cleaner.
Reference: https://reactjs.org/docs/hooks-state.html.
And if you want to check out another highly useful hook, here’s effect
: https://reactjs.org/docs/hooks-effect.html
And you can even write your own hooks! https://reactjs.org/docs/hooks-custom.html