Tutorial

Introduction to React Hooks

Published on December 6, 2018
Default avatar

By joshtronic

Introduction to React Hooks

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Function components are great, but they are limited to do exactly what they are told by way of properties. The moment you need them to be mindful of their state, you are forced to rewrite them as class components. Fortunately, a lot of class component-only features are making their way to function components.

One such feature, which is currently in alpha and is expected to land in React v16.7, is Hooks. Hooks brings statefulness and lifecycle methods, previously only available to class components to function components.

Getting Started

As mentioned, this feature is currently in alpha but is expected to be a part of the next point release of React. Because of this, we will need to specify a version when adding React to our project.

# Via npm
$ npm install --save react@next react-dom@next

# Or via Yarn
$ yarn add react@next react-dom@next

What Makes a Hook?

  • Must start with the word use.
  • Hooks can only be called from within function components and custom Hooks. This has the added bonus of keeping your component logic grouped together nicely.
  • Only use Hooks at the top level, never from inside of conditionals, loops, or nested functions within your function component. This is to help ensure the Hooks are called in the same order with each render.

Component State

To create a stateful function component using Hooks, we will need to initialize the state using useState from the React package.

This method accepts a parameter to set the initial state, and returns an array containing the current state and a function to set the state.

Here’s a stateful function component that keeps track of a color that is set at random every time the button is pressed:

import React, { useState } from "react";
import { render } from "react-dom";

function StatefulFn() {
  const [color, setColor] = useState(false);

  function onClick() {
    const colors = [
      "#008F68",
      "#6DB65B",
      "#4AAE9B",
      "#FAE042",
      "#EFBB35",
      "#DFA612"
    ];

    setColor(colors[Math.floor(Math.random() * colors.length)]);
  }

  return (
    <button onClick={onClick} style={{ backgroundColor: color }}>
      Click to Change Button Color
    </button>
  );
}

const container = document.createElement("div");
document.body.appendChild(container);
render(<StatefulFn />, container);

The useState method is very much intended to be used with a single value, and not a state object the way class components work. Because of this, we either have to maintain a state object manually ourselves, or more simply, just call useState more than once to keep track of each variable in our state:

const [color, setColor] = useState(false);
const [size, setSize] = useState('medium');
const [reptile, setReptile] = useState('alligator');


Component Lifecycle

Another gotcha of using function components has been their lack of lifecycle methods. Another part of the Hooks feature is the addition of useEffect which is a combination of componentDidMount, componentDidUpdate and componentWillUnmount.

In more simple terms, useEffect will fire after the initial render and any subsequent re-renders.

If you’re familiar with the React class component lifecycle, you know that it’s bad to put code with side effects in your render method. That’s why the lifecycle methods exist to begin with.

One such side effect is firing off a network request, and then updating the state with a value that’s returned. In the next example, I’m going to simulate a very slow network connection by using setTimeout and will display a loading message while we wait:

import React, { useEffect, useState } from "react";
import { render } from "react-dom";

function EffectedFn() {
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setTimeout(() => {
      setLoading(false);
    }, 1000 * 10);
  });

  return (
    <div>
      {loading && <span>Loading...</span>}
      {!loading && <span>All Done!</span>}
    </div>
  );
}

const container = document.createElement("div");
document.body.appendChild(container);
render(<EffectedFn />, container);

Something cool about useEffect is that it doesn’t block the browser from updating the screen the way componentDidMount and componentDidUpdate do. This helps to ensure that things seem responsive and snappy to your users!

To help improve performance even further, especially when working with multiple state variables, you can tell useEffect to only fire when a certain value has changed:

useEffect(() => {
  setTimeout(() => {
    setLoading(false);
  }, 1000 * 10);
}, [loading]);

But I don’t wanna use Hooks!

What’s really great about Hooks is you don’t have to use them if you don’t want to. If you’re keen on using classes, you can keep on truckin’. If you’re scared that you will need to update all of your existing, non-hooked functions, don’t be.

Hooks are 100% backwards compatible so there’s no need to scramble to update any existing code. Classes aren’t going anywhere and if/when you’re ready to start using Hooks, as long as you’re on a version of React that supports it, you can do so.

Conclusion

Personally, I’m sick and tired of porting functions to be classes when I need state and lifecycle support so for me, Hooks are a very welcome addition.

Plus, it’s super easy to create your own hooks or use hooks developed by the greater React community. There are already collections of available hooks that are popping up left and right.

If you’re like me and ready to start using Hooks today and want to see the code from this article in action, head over to CodeSandbox.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
joshtronic

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel