
React: Hooks in functional components
As told in a previous post, nowadays you can use Hooks in React, allowing you to use state
and lifecycle methods without problems. Read further to know how.
State Hook
A Hook is a special function that allows you too hook into React. The most commonly used one is the State Hook, because a lot of components use state
to hold and update data. Let's start with a small example of a stateful component.
1 2 3 4 5 6 7 8 9 10 11 12 13
// stateful component import React from 'react'; class Album extends React.Component { constructor(props) { super(props); this.state = { title: 'Strange Days', artist: 'The Doors' }; } }
If we want to do the same, but stateless, we get the functional component below that's using the useState
Hook.
1 2 3 4 5 6 7
// functional component, using a Hook import React from 'react'; function Album() { const [title, setTitle] = useState('Strange Days') const [artist, setArtist] = useState('The Doors'); }
In the above example you can see that the declaration of state
has been replaced with the useState
Hook. Behind the scenes the same happens: the state variables – "title" and "artist" in this case – are being declared and initialized. The argument that is passed in useState
is used as default value of the variable. Most likely this will be an empty string, true
/false
…
The return value of useState
is an array holding two values: de current state of the variable and an update function. These are the same as this.state.title
and this.setState
in a stateful component. I also want to point out that the names of both variables in the return value can be chosen freely; it can be something like const [title, modifyTitle]
as well – although the general naming convention is with set.
Read and update
Now that we know how to create a state variable, the only question left is how to use it. The example below speaks for itself.
1 2 3 4 5 6 7 8
// stateful component // read <p>My favorite album is "{this.state.title}" by {this.state.artist}</p> // update onChange = event => { this.setState({title: event.target.value}) }
1 2 3 4 5 6 7 8
// functional component // read <p>My favorite album is "{title}" by {artist}</p> // update onChange = event => { setTitle(event.target.value) }
Lifecycle methods
Functional components don't have lifecycle methods by default, but luckily there's a Hook: useEffect
. useEffect
will be called automatically when one of the given variables changes. A perfect replacement for componentDidMouunt
and componentDidUpdate
!
Both examples below will write the given title to the local storage when the input field changes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// stateful component class Album extends React.Component { constructor(props) { super(props); this.state = { title: localStorage.getItem('title') || '' }; } componentDidUpdate() { localStorage.setItem('title', this.state.title); } onChange = event => { this.setState({ value: event.target.value }); }; render() { return ( <input type="text" value={this.state.title} onChange={this.onChange} /> ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// functional component function Album() { const [title, setTitle] = useState(localStorage.getItem('title') || ''); useEffect(() => { localStorage.setItem('title', title); }, [title]); onChange = event => setTitle(event.target.value); return ( <input type="text" value={title} onChange={onChange} /> ); }
Thanks to Hooks, there is nog longer any reason to rework your components into functional components – with the exception perhaps of very complex components. To learn more about Hooks, you can read the official documentation.