React allows you to build user interfaces. React 16.8 introduced a new feature called Hooks. In this tutorial, we are going to look into the why aspect of React Hooks.

React without hooks

Let us see the current state of creating user interfaces in React.

Components are the building blocks in React. You can create a component by extending the Component or by using a functional component. Below are the example of component created using class and function.

Class React Component

import React, { Component } from "react";
import ReactDOM from "react-dom";

class App extends Component {
  render(){
    return (
      <div className="App">
        <h1>Techdomain</h1>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Functional React Component

import React from "react";
import ReactDOM from "react-dom";

function App() {
  return (
    <div className="App">
      <h1>Techdomain</h1>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

What are the problems with above approach?

Wrapper Hell

Higher Order Components (HOCs) is a pattern that emerges from React's compositional nature. Due to HOCs pattern, we are able to reuse code between the components. But the downside is that creating two many HOCs can lead to many components wrapped around child components - called as wrapper hell. Here is an example of wrapper hell.

<WithRouter>
 <WithTheme>
   ...
     <App />
   ...
 </WithTheme>
</WithRouter>
Components follow hierarchy

One of the main problem with component based approach is that code reuse becomes difficult. Every time you build a generic higher order component, it wrapper around a child component. As mentioned above, this leads to wrapper hell and also makes it difficult to understand. It also becomes difficult to navigate through the complex component hierarchy.

Unrelated props are passed around

When we have many components wrapped in hierarchy, many props are passed from parent to child, and all of these props may not be used by intermediate component.

Classes cause performance issues

Class components make it difficult for the today's compiler to minify completely. Hot reloading of components - refreshing apps by hot replacing the components with changed components - is flaky and unreliable.

Introducing React Hooks

React Hooks, as the name suggests, allow you to hook into the features of React - state and life cycle methods without the need to create HOCs or class components.

As long as your function follows the rules of hooks, you can easily add React Hooks inside the function and use the state and life cycle methods of React.

For example, if you want to use the "state" feature of React inside a function (as long it follows rules of hooks), you can do so as shown below.

// this will return name with initial value as "techdomain" and a function called setName which will allow you to change the name.

const [name, setName] = useState('techdomain');

Similarly, we add business logic inside the lifecycle methods in React classes. This can be replicated using the useEffect hook.

class App extends Component{
   componentDidMount(){
     // pseudo code for a function which makes api call and sets the state
     this.makeApiCall();
   }
   render(){
    return (<div></div>)
   }
}
import { useState, useEffect } from 'react';

function App(){
   const [data, setData] = useState({})
   const { name } = data;
   useEffect(()=>{
     this.makeApiCall();
   })
   return <div>{data.name}</div>
}

useContext lets you subscribe to React context without introducing nesting:

function Example() {
  const locale = useContext(LocaleContext);
  const theme = useContext(ThemeContext);
  // ...
}

And useReducer lets you manage local state of complex components with a reducer:

function Todos() {
  const [todos, dispatch] = useReducer(todosReducer);
  // ...

Advantages of React Hooks

  • Helps avoid wrapper hell
  • It is easier to migrate a non-react app to React app using React Hooks*.
  • You can build custom hooks as well which encapsulate complex logic.
  • Data sharing is easier compared to classes
  • Code minification is more compared to class components.

*React Hooks can only be used in React functional components or a custom hook function, and not in a javascript function.