React 16.7 Hooks Tutorial

React Hooks are a new feature recently released by the React team. It's included in React 16.7 which is in its Alpha version as of this writing.

React Hooks Tutorial

In this tutorial, we'll learn to migrate our previous project created with React and Django to use function components and React Hooks instead of class components, life-cycle methods and the state object.

Prerequisites

You need to have:

  • Python 3, Pip and venv installed for running the back-end API,
  • Node.js 6+, npm 5.2+ and create-react-app for running the React app,
  • Git for cloning our project from GitHub.

Cloning and Setting Up our React/Django Project

First let's start by cloning our full-stack React/Django project.

Navigate to your home directory and create a virtual environment using the venv module:

$ cd ~
$ python3 -m venv ./env

Activate the created virtual environment using:

$ source env/bin/activate

Using Git run the following command from your terminal:

$ git clone https://github.com/techiediaries/django-react.git django-react-hooks

Next, navigate to your cloned project using:

$ cd django-react-hooks

Next install the dependencies using pip:

$ pip install django djangorestframework django-cors-headers

Now, navigate to the frontend folder and install the dependencies using npm:

$ cd frontend
$ npm install

This will install React and Axios.

Since, we need to use React Hooks; we have to install the latest version of React which is react@16.7.0-alpha.0.

You simply need to run the following commands:

$ npm install react@16.7.0-alpha.0 --save
$ npm install react-dom@16.7.0-alpha.0 --save

This will install the latest react and react-dom alpha versions which support React Hooks.

Introduction to React Hooks

Before migrating our demo project to functional components and React Hooks let's first understand what hooks are and why we need to use them.

So why all that buzz about React hooks? And what can they do for you?

Simply, if you need to use React features like state and life-cycle events/methods (which is often most of the times) you would need to use/switch to classes by extending React.Component. But, that's not the case any more; with hooks you can now use those commonly needed features in your functional components.

What is A React Hook?

React is nowadays the most popular and used UI library in the world. The team is constantly trying to improve both the performance of the library and the developer experience by adding new features that makes developer's lives more easy.

As of this writing, most React developers are very existed about a new React feature -- Hooks, they are now on alpha version and they will be included in React 16.7.

A React Hook is a new feature (that's only available in alpha as of this writing) to use the React.Component features in a functional component.

The most used features are:

  • The state object,
  • Life-cycle events like componentWillMount, componentDidMount, componentWillUpdate and componentDidUpdate etc.
  • context,
  • refs etc.

Saying that, class-based components are still useful. It's just that you have now more options to do the same thing and It's up to your preferences to use either classes or functions to build your React apps without being limited by the lack of features with any option.

Just like with the other React concepts; they have fancy names but they are actually simple concepts to understand. Hooks are also simple functions that allow developers to “hook into” React state and life-cycle methods from functional components. Hooks are not available in class-based components — bu instead they allow you to use React without JavaScript classes. If you prefer to use functions instead of classes (which is recommended in JavaScript) you can simply start using Hooks without worrying about migrating your whole apps to classes.

Hooks enables you to use “class-features” In React by providing a set of built-in functions such as:

  • The useState() hook for using states from function components,
  • The useEffect() hook for performing side effects from function components (it's equivalent to life-cycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount in React classes),

  • The useContext() hook for subscribing to React Context from a function component,

  • The useReducer() hook for managing the state of components with a reducer

  • useRef for React Refs,

  • The useCallback hook for callbacks,

  • The useMemo hook for memoized values,

  • The useImperativeMethods hook for imperative methods,

  • The useMutationEffect hook for mutation effects,

  • The useLayoutEffect hook for layout effects.

You can also create your custom Hooks to re-use any stateful behavior between different components.

In other words Hooks lets you have stateful functional components.

React Hooks are typical JavaScript functions, with the exception that they need to obey to two rules:

  • Hooks need to be used at the top level i.e not inside nested functions or other JS constructs like loops or if conditions etc.
  • Hooks need to be used in functional components not in regular JavaScript functions. You can also call built-in Hooks from your custom Hooks

The React team provides a linter plugin that can be used by developers to make sure these rules are respected so Hooks can work as expected in your app.

Example Accessing State in Functions with useState()

Now that we have seen some theory about React Hooks. Let’s see a simple example of a stateful function component with the useState() hook. Let’s start with a simple stateless function component that we are familiar with.

This a simple React app with one ContactPage function component:

import React from 'react';
import { render } from 'react-dom';

function ContactPage(props) {
   return (
    <div>
     <h1>Contact Page</h1>
    </div>);
}

render(
  <ContactPage />,
  document.querySelector('#root'));

In the old React, If we want to keep or work with any state in this component we'll need to convert it into a class component. For example, let's say we need to use an email variable in our component. This is what we'll have to do:

class ContactPage extends React.Component {
  state = {
    email: 'a@email.com'
  }


  render() {
    return (
     <div>
       <h1>Contact Page</h1>
        <p>My email is {this.state.email}</p>
       </div>
    );
  }
}

We rewrite our component to use a class instead of a function so we can be able to use the state object.

Now, thanks to React Hooks we can simply use this alternative code without re-writing you component:

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

function ContactPage(props) {
   const  [email, setEmail]  =  useState('a@email.com');
   return (
    <div>
       <h1>Contact Page</h1>
        <p>My email is {this.state.email}</p>     
    </div>);
}

This is our regular function but it's now equipped with a state using the useState() hook function.

Note that hook functions start with the use word which is another rule of Hooks.

The useState() hook takes an initial state and returns an array with two elements: the current state, and a function to set the state. In our example, we pass in the a@email.com string as initial state
and we use array destructing assignment to grab variables and rename them properly. We can access the current piece of state using email and the function to set the state using setEmail.

The useState() hook provides us with two variables that we need to rename with proper names. To be able to rename these variables properly, you need to know these two things:

  • The first element of the returned array presents the value which equivalent to this.state in class components.
  • The second element is a function to set that value which is equivalent to this.setState() in classes.

The state can be any valid JavaScript object.

React functional components have no state, but thanks to the useState() hook we can have little pieces of state when we need them.

Example using The Effect Hook in React

Now that we have seen the State Hook with example and understand why we need to use it - which is to lets us use state in React functional components. Let's see an example using the Effect Hook to be able to perform side effects in our functional components without resorting to use life-cycle methods which are only available in class components.

Effect Hooks are equivalent to componentDidMount, componentDidUpdate and componentWillUnmount life-cycle methods.

Side effects are common operations that most web applications need to perform, such as:

  • Fetching and consuming data from a server API,
  • Updating the DOM,
  • Subscribing to Observables etc.

Effect Hooks will run after every render, including the first render.

import React, { useState } from 'react';

function Customers() {
  const [customers, setCustomers] = useState([]);

  useEffect(() => {
    fetch('127.0.0.1:8000/customers')
      .then(response => response.json())
      .then(data => {
        setCustomers(data); // set customers in state
      });
  }, []); 
}

We first use the useState() with an empty array for the initial state to create a customers state.

Next, we'll use the useFetch() hook to run a side effect which is sending a request, using the Fetch API, to an API endpoint that returns a list of customers.

We finally use the setCustomers() method to assign the returned data to the customers state variable.

Conclusion

You can combine many types of hooks or use the same hook multiple times in your application without any problem. In fact, in most apps, you'll have to use them both in order to be able to fully use functional components without resorting to any feature in class components.

In the next part, we'll see a real-world example of using React Hooks with Axios and a Django API.


comments powered by Disqus