— React — 2 min read
A couple of weeks ago, as of the writing of this article, Dan Abramov took onto the stage to introduce React Hooks to the React community at React Conf 2018 in Henderson, Nevada. And at first glance, I was encouraged for as much as it introduces new API, it makes it easy for React developers to use the same features we have been using for years but now, more efficiently and elegantly. Most importantly, they don’t introduce breaking changes and are 100% backward compatible.
Hooks are a new feature proposal that lets you use state and other React features without writing a class. That’s right! You can write a function component and have access to its local state and also its lifecycle methods 🎉🎉
They are currently in React v16.7.0-alpha; You can follow the discussions and developments here.
Any API introductions should be backed up with motivation or reason as to “why,” and this is no different. Below are some of the reasons why;
We think Hooks are our best shot at solving all of these problems. Hooks let us organize the logic inside a component into reusable isolated units. — Dan Abramov
Hooks are categorized into two categories: Basic and Additional Hooks. I am going to demo useState and useEffect. Be sure to check the others out, for they will come in hand in your development work. I will write about the other hooks in subsequent series' of articles.
We'll create a controlled form input for setting a name.
1import React from 'react';2
3const Counter = () => {4 const [name, setName] = React.useState('John Doe');5
6 const handleNameChange = (e) => setName(e.target.value);7
8 return (9 <div>10 <form>11 <label htmlFor="name">Your name</label>12 <input id="name" value={name} onChange={handleNameChange} />13 </form>14 <hr />15 <p>{`Your name is ${name}`}</p>16 </div>17 );18};
Draw your attention on the highlighted line of code which, shows the signature of the useState hook. It returns a destructured pair, the current value, and an updater function that lets you update that specific value. In this case, we have name
and setName
, which holds the current name value and updates the name, respectively. The useState hook takes an optional value, which will be its initial value. In this case, we have John Doe
.
We then data-bind the input to the name value. We achieve this by passing the name
to the value of the input field along with a synthetic-event onChange
handler, as depicted below.
1<input id="name" value={name} onChange={handleNameChange} />
The handleNameChange
function passes the value of the input to the setName
updater function, which completes our two-way data-binding.
Below are some points to note when using useState;
localStorage
This hook is used for making side effects like making API calls, subscriptions or manually changing the DOM in React components. This is the equivalent of componentDidMount, componentDidUpdate and componentWillUnmount but in a single unified API.
To demonstrate this, we will make an API call to the Star Wars API.
1import React, { useState, useEffect } from 'react';2
3export default function App() {4 const [data, setData] = useState([]);5 const [loading, setLoading] = useState(false);6
7 const controller = new AbortController();8 const signal = controller.signal;9
10 const fetchData = () => {11 setLoading(true);12 fetch('https://swapi.dev/api/people/1/', { signal })13 .then((res) => res.json())14 .then((data) => {15 setLoading(false);16 setData(data);17 })18 .catch((error) => {19 setLoading(false);20 console.error(error);21 });22 };23
24 useEffect(() => {25 fetchData();26 return () => {27 controller.abort();28 };29 }, []);30
31 return (32 <div className="App">33 <h1>Hello CodeSandbox</h1>34 <h2>Start editing to see some magic happen!</h2>35 {loading && <p>Loading...</p>}36 {!loading && <pre>{JSON.stringify(data, null, 2)}</pre>}37 </div>38 );39}
Draw your attention to the highlighted lines of code. We are calling the useEffect
hook and passing it a callback function. The callback calls fetchData
function which pulls data from an API hence causing a side effect.
The component might unMount
before this function is settled, hence we return
a clean up function which cancels the request using the AbortController
API to avoid any memory leaks. We finally pass a dependancy for this function in our case, an empty array
. This tells React to call this function only once on Render
. This is the equivallent of componentDidMount
when using class
Components. If we didn't pass any dependacies, the function would be called over and over infinitely.
Below is the signature of useEffect
;
1useEffect(2 () => {3 /* Make side effects e.g;4 - subscriptions5 - API calls6 - DOM manipulation e.t.c7
8 */9 return () => {10 /* do some cleanup work like;11 - cancelling any unsettled network requests12 - unsubscribing to any subscriptions e.t.c13 */14 };15 },16 [17 /*dependacies*/18 ]19);
Hooks are Javascript functions and they come with some rules;
Hooks allow you to write more cleaner code with less boilerplate. Below are some reactions from the community.
Hooks are awesome and they let you enjoy the same API's we've been using, only this time, with a little less code.
You can take this further by writting your custom hooks that you can re-use on your code base. There are more hooks that I haven't touched on here. You can learn more about them on here.