React Hooks
2018-10-27
React Conf 2018 just ended. Even though I didn’t watch any of the videos (yet), it seems like an upcoming feature proposal called Hooks, available in React v16.7.0-alpha, was presented there. And the offical React docs already have information on it. One sentence in there simply puts it this way:
Hooks let you use more of React’s features without classes.
More specifically, Hooks allow function components to “hook into” state and lifecycle features. I can imagine that quite a few people have been waiting for this… But the docs also explicitly state (no pun intended - the first time I get to use this phrase on my blog) that there are no plans to remove classes from React. Still, one reason given for introducing this new approach is to deal with some of the drawbacks of ES6 classes.
While I’m rather agnostic about classes, the React docs take them to be the “biggest barrier to learning React”. That’s heavy. In my book things like the this
keyword cannot pose such an issue as to prevent people from actually using React. But I have no data to back this up, of course. Another, soley technical reason given in the docs is that classes seem to stand in the way of certain optimizations like minifaction and some more advanced ones.
But back to Hooks. Currently React offers three basic ones: useState
, useEffect
and useContext
. There are additional ones, but according to the docs they are either variants of the basic ones or cover edge cases. You can even define custom hooks, but that’s a topic for another day. So far I also just looked into the useState
hook, as it will possibly be the one most commonly used.
Here’s an example based on the one from the docs:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
useState
takes a default value for a state variable and returns an array with two items. The first item is the current value, and the second is a function to update it. You can name them however you want, but it makes sense to keep them semantically aligned (value
- setValue
, items
- setItems
etc.). You can also have multiple state variables and they can consist of whatever you need: strings, numbers, arrays or objects. One thing to keep in mind if you are going to use a non-primitive value is that unlike setState
in a class, a hook’s update function will not do any merging but replace the old value with the new.
State variables are only created the first time the component renders. During the next renders, useState
provides the current state, meaning React takes care of preserving the state variables between function calls. Without this they would get “trashed” after each call, a problem you don’t have with classes, as in them the state can be kept outside the render method.
Here is the same component implemented using a class:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
// this makes use of the ES7 class properties proposal
// which is already commonly used to bind a method to its class
updateCount = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.updateCount}>Click me</button>
</div>
);
}
}
It’s a contrived example, but it shows that simple components that still need some state can be written in a more concise way as function components using useState
.
Hooks is still in beta, mind you. But it sounds like it will be going into the 16.7 relase. And since there is a lot more to Hooks, be sure to head over to the React docs and read up on it.