What are React Hooks

React Hooks are a type of function that allows the users to hook into react state and life-cycle features from function components. React provides built-in hooks like useState, useEffect, useReducer, useRef, use Callback, useContext, and useMemo and we can also create your own custom hooks.

React hooks are available from React version of 16.8. Before the introduction of hooks, the state can be maintained only in the class component not in the functional component. After the introduction of hooks, the state can be maintained in functional component too.

The idea of using hooks makes it possible to create full-fledged functional components while using all the React features. This allows us to make everything easier, unlike classes.

The main problems which were solved by the release of hooks in React 16.8:

  • Wrapper ****Hell
  • Classes
  • Side effect

In ReactJS, the most difficult thing is to reuse logic in stateful components. Before the appearance of React hooks, there was no way to reuse the logic of behaviour to the component, for example, to connect it to the store.

The following examples make it clear why hooks are useful.

Using Classes :

import React, { Component } from 'react';

class App extends Component {
  constuctor(props) {
    super(props);    
    this.state = {
      isButtonClicked: false,
    }    
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.setState((prevState) => ({
      isButtonClicked: !prevState.isButtonClicked,
    }));
  }

Using Hooks :

import React, { useState } from 'react';

const App = () => {
  const [isButtonClicked, setIsButtonClickedStatus] = useState(false);

  return (
    <button
      onClick={() => setIsButtonClickedStatus(!isButtonClicked)}
    >
      {isButtonClicked ? 'Clicked' : 'Click me, please'}
    </button>
  );
};

From this, we can understand that hooks work similarly to such concepts as a state.

Rules of Using React Hooks

Hooks are just JavaScript functions, but they require two specific rules:

  • Hooks should be performed at the very top of the function hierarchy which means that the users should not call hooks in conditions and loops, otherwise the reaction cannot guarantee the execution order of hooks.
  • We should call hooks only in React functions or functional components or call hooks from custom hooks.

Advantages of React Hooks

As we have already seen, React Hooks makes our life easier in a lot of ways as stated below:

Improving Readability of Component Tree

The "useContext" hook has been a blessing for greatly improving the readability of JSX as it allows context values to be read outside of JSX. This was also previously possible in class components by using the static "contextType" property but is even cleaner with "useContext".

Aside from the code being easier to read it is also much easier to read the component tree in the React dev tools when debugging. The value of this really adds up for components that previously used multiple nested contexts.

Encapsulating Side Effects

With class components, the setup and teardown of side effects were split across multiple lifecycle methods like the event listeners could be added in "componentDidMount" and later removed in "componentWillUnmount". If any component has multiple side effects this could lead to less readable code with a related logic split across several incohesive lifecycle methods.

But the "useEffect" solves this problem by handling both the setup and teardown of side effects. It does so by allowing the effect function to return a function to teardown the effect. It is evident from the below example:

useEffect(() => {
  window.addEventListener("resize", resizeHandler);

  return () => window.removeEventListener("resize", resizeHandler);
}, []);

Composable and Reusable Logic

Custom hooks are considerably a great mechanism for sharing logic across various components. A custom hook is simply a function that uses one or more React hooks and it can be called within a functional component, just like a standard hook.

A nice example is a custom hook for tracking the result of a media query and returning this state to the component. It demonstrates how hooks can be combined. It uses "useEffect" to set up an event listener to track changes in whether a media query is matched or not. It also uses "useState" to store this state and return the result to the calling component.

function useMatchMedia(mediaQuery) {
  const [matches, setMatches] = useState(window.matchMedia(mediaQuery).matches);
  useEffect(() => {
    const updateMatches = event => {
      setMatches(event.matches);
    };
    const mediaQueryList = window.matchMedia(mediaQuery);
    setMatches(mediaQueryList.matches);
    mediaQueryList.addListener(updateMatches);
    return () => mediaQueryList.removeListener(updateMatches);
  }, [mediaQuery]);

  return matches;
}

Summary

  • In this article, we explored the concepts of React Hooks which allow the users to hook into react state and life-cycle features from function components.
  • We learned how classes and hooks are different with suitable examples.
  • We understood the various advantages of working with React Hooks like improving the readability of the component tree, encapsulating side effects and providing composable and reusable logic.