React – Hooks

A functional component typically lacks many of the essential features that are present in class components. It does not have any state or important lifecycle methods like componentDidMount and componentDidUpdate.

A functional component was initially designed to handle UI and data presentation and not maintain any internal data for itself like state. The primary purpose was to be a presentational component and not a container component. In this lesson, we will explain hooks and how they help us use many features from the class components.

Introduction to Hooks

A hook is a React Method that provides access to those react’s features to functional components that are generally not available.
To state it technically, “It taps into the React library, then hooks into the core features, and makes them available for functional components.”

Hooks are relatively new in React and were introduced after the version 16 release. Hooks have the below characteristics:

1. Easier for beginners

It is easier for beginners to learn React and apply its core concepts to functional components. This way, a learner must not know any object-oriented programming or classes, methods, the “this” keyword, and related jargon.

2. Offers Flexibility to Developers

Developers can now extend the previously written components for React Projects using functional components to use state and other essential features without converting to class components.

3. Offers More Choice and Options

More choices and options allow the developer to code according to his preference to use functional or class components.

Fundamental Hooks

We will discuss the two fundamental hooks in this lesson:

1. useState and 2. useEffect

All hook names start with a “use” prefix that identifies them as a React Hook. Other additional hooks like useReducer, useCallback, useContext, useRef, etc., have fewer and advanced use cases.

React even allows you to define your custom hooks for more control. You can export Hooks as a method of the React instance. Example usage: React.useState(), React.useEffect(), etc.

Important Hook Rules

Before using hooks, it is essential to know some of the restrictions and rules:

  1. Use/call hooks only inside functional components.

Don’t call hooks inside:

  • Class Components.
  • Normal functions except functional components.

2. Use hooks only at the top-level code inside a functional component.

Call hooks only inside the outermost code of the functional component. You should not call Hooks inside any:

  • Loops
  • Conditional Statements (if-else, switch, ternary operator)
  • Return Statements.
  • Nested Functions

The useState() Hook

The useState() hook allows us to use states inside a functional component. It takes an optional initial value and returns an array with two elements:

1. The particular state having the initial value.

2. The state updater function. It is normally named by prefixing the name of the associated state with “set”.

import React from 'react'
export default function MyComponent() {
    /* destructure the returned array */
    const [status, setStatus] = React.useState('inactive') ; 
    /* status is now a state variable having ‘inactive’ value */
    /* 
    Call setStatus updater function inside handlers for events like button click: setStatus(updatedValue).
    */
  return (
  {/* any changes to the status by setStatus() will be reflected */}
      <div>Status: u{status}</div>
  )
}

The updater function in our example, setStatus() takes a value as its parameter and updates the related state with the given value.

To define multiple states, you have to call useState multiple times.

const [product, setProduct] = useState('phone');
const [status, setStatus] = useState('active');
// update the product on button click…
setProduct('jeans')
/* using setProduct you can only update its related state(i.e. product) and not the status. */

The useEffect() Hook

This hook tries to provide the functionality of three lifecycle hooks from class components, namely: componentDidUpdate, componentDidMount, and componentWillUnmount.

Features

Surprisingly, the same hook (useEffect) can behave as different lifecycle methods, as shown in the image below.

You can replicate everything possible on those three lifecycles methods inside useEffect(). So, using useEffect, you can:

  1. Perform side effects (calling external API or fetching some data from a server).
  2. Run some code when the functional component mounts for the first time (similar to componentDidMount).
  3. Run code every time the functional component renders. (similar to componentDidUpdate).
  4. Execute code before the functional component unmounts. (similar to componentWillUnmount).

Syntax and Forms

The useEffect() hook takes a callback function(called an effect) as its first parameter. It applies the effect (i.e., executes the callback function) every time a component updates and renders.


1. componentDidUpdate() with useEffect()

It just behaves like the componentDidUpdate() lifecycle by default.

import React from 'react'
export default function MyComponent() {
    React.useEffect(() => {
      /* 
      this function will run after every render to the component …
      */
    })
    const [status, setStatus] = React.useState('inactive') ; 
    return (
        <div>{status}</div>
    )
}

2. Conditional componentDidUpdate() with useEffect()

useEffect() also takes a second argument to skip unnecessary updates. It is an array of values to watch for changes. If you pass this 2nd argument, useEffect will apply the effect only if one of the values of the array changes.

const [status, setStatus] = useState('inactive');
const [product, setProduct] = useState('phone');
useEffect(() => {
    /*
    It will run only for every ‘status’ change. It will ignore all other prop/state updates like ‘product’.
    */
}, [status]);

It is similar to componentDidUpdate() that runs some code only when a particular prop/state changes.

Equivalent code using componentDidUpdate() for class components:

componentDidUpdate(prevProps, prevState){
        if(prevState.status !== this.state.status){
  		  /* this part of code will run if ‘status’ changes */
  		  }
}

3. componentDidMount() with useEffect()

If you pass an empty array [] as the 2nd parameter, the effect is applied only once when the functional component mounts.

useEffect(() => {
    /* 
      will run only once in the beginning after the component mounts 
    */
}, [])

4. componentWillUnmount() with useEffect()

You can optionally return a function from the callback/effect supplied to useEffect(). Any code that you want to execute before the component unmounts, should be included in the returning function.

useEffect(() => {
    /* will run only once in the beginning */
    return () => {
    /*
    Code for componentWillUnmount() goes here. Perform clean ups like unsubscribing from listeners, clearing timers, etc. 
    */
}
})

Summary

Hooks are the features in ‘React’ that give functional components access to state, lifecycle methods, reducers, and more. The two most important hooks are useState(initialState) and useEffect(callbackFunction, arrayValuesToWatch).

  • useState() provides access to the state, and returns an array with a pair consisting of a state and updater function.
  • useEffect() provides the functionality of different lifecycle methods.

Hooks only work inside functional components. It is used a lot in many projects as React promotes the benefits of using hooks. This does not mean that class components will be removed anytime soon.

Back to: React Tutorial > Learn React

Leave a Reply

Your email address will not be published. Required fields are marked *