ReactJS: Hooks

SAMEER MISTRY
7 min readMay 31, 2021

Hooks are the new feature introduced in the React 16.8 version. It allows you to use state and other React features without writing a class.Hooks are backward-compatible, which means it does not contain any breaking changes.

Hooks provide a more direct API to the React concepts you already know: props, state, context, refs, and lifecycle.

When to use a Hooks

If you write a function component, and then you want to add some state to it, previously you do this by converting it to a class. But, now you can do it by using a Hook inside the existing function component.

Rules of Hooks

  • Hooks can be call at the Top level only in functional components.
  • You cannot call Hooks from regular JavaScript functions. Instead, you can call Hooks from React function components. Hooks can also be called from custom Hooks.
  • Don’t call Hooks inside loops, conditions, or nested functions.
  • Always use some dependency for calling API in useEffect hook otherwise it will go into infinite loop because this hook runs after every render.
  • User can create any custom hooks with defined rules.

Example(Without Hooks):

import React, { Component } from 'react';class ClassCounter extends Component {constructor(props) {super(props);this.state = {count:0}}incrementCount = () =>{this.setState({count:this.state.count + 1})}render() {return (<div><button onClick={this.incrementCount}>COUNT : {this.state.count}</button></div>);}}export default ClassCounter;

Example(With Hooks):

import React , {useState} from 'react';function HooksCounter() {const [count,setCount] = useState(0);return (<div><button onClick={()=>setCount(count + 1)}>COUNT : {count}</button></div>);}export default HooksCounter;

Output:

In both example output will be same.so with the use of react hooks we can reduce the line of code.

Hooks State

Hook state is the new way of declaring a state in React app. Hook uses useState() functional component for setting and retrieving state.

useState returns a pair: the current state value and a function that lets you update it.It follows the array de-structuring concept like for defining state

Ex. const [count, setCount] = useState(0);

  • Here const count is similar to the this.state.count in class and it can be used in entire functional component.
  • setCount is the function to update count state and it’s similar to the this.setState in class, except it doesn’t merge the old and new state together.
  • You can call this function from an event handler or somewhere else.
  • To use this count state we can directly call it as {count}.
  • “useState” hook can be called multiple times in entire functional component.

Example:

import React , {useState} from 'react';function Counters() {const initialCount = 0;const [count,setCount] = useState(initialCount);return (<div>COUNTER : {count}<button onClick={()=>setCount(count + 1)}>Increment</button><button onClick={()=>setCount(count - 1)}>Decrement</button><button onClick={()=>setCount(initialCount)}>Reset</button><button onClick={()=>setCount(count + 5)}>Increment 5</button><button onClick={()=>setCount(count - 5)}>Decrement 5</button></div>);}export default Counters;

Output:

Hooks Effect

The Effect Hook allows us to perform side effects (an action) in the function components. It does not use components lifecycle methods which are available in class components. In other words, Effects Hooks are equivalent to componentDidMount(), componentDidUpdate(), and componentWillUnmount() lifecycle methods.

  • You can call this hook for calling API or any callback functions with passing dependencies array as second argument.
  • By default React runs the effect after every render including first render and have access of states and props inside it.

Example:

import React , {useState ,useEffect} from 'react';function HookUseEffect() {const [x,setX] = useState(0);const [y,setY] = useState(0);const logMousePos = e => {console.log("Mouse Event Call");setX(e.clientX)setY(e.clientY)}useEffect(()=>{console.log("Use Effect Call");window.addEventListener('mousemove', logMousePos);return () =>{console.log("Component is Unmount now");window.removeEventListener('mousemove',logMousePos);}},[])return (<div>Hooks Call X : {x}  Y : {y}</div>);}export default HookUseEffect;

Output:

Built-in Hooks

The built-in Hooks can be divided into two parts, which are given below:

1)Basic Hooks

  • useState
  • useEffect
  • useContext

2)Additional Hooks

  • useReducer
  • useCallback
  • useRef
  • useMemo
  • useLayoutEffect
  • useDebugValue
  • useImperativeHandle

useContext Hook

React’s useContext hook makes it easy to pass data throughout your app without manually passing props down the tree.It makes up part of React’s Context API . Context can make a nice simple alternative to Redux when your data is simple or your app is small.

const value = useContext(MyContext);

Example:

import React, { useContext } from 'react';const themes = {light: {foreground: "red",background: "#526332"},dark: {foreground: "#ffffff",background: "blue"}};const ThemeContext = React.createContext(themes.light);function AppContext() {return (<ThemeContext.Provider value={themes.dark}><HookContext /></ThemeContext.Provider>);}function HookContext(props) {return (<div><ThemedButton /></div>);}function ThemedButton() {const theme = useContext(ThemeContext);return (<button style={{ background: theme.background, color: theme.foreground }}>I am styled by theme context!    </button>);}export default AppContext;

Output:

useCallback Hook

This hook is useful when you have a component with a child frequently re-rendering

This reasoning is far from the truth. Moreover, such usage of useCallback() makes the component slower.

Example:

import React, { useState, useCallback } from 'react'const functionsCounter = new Set()const HooksCallBack = () => {const [count, setCount] = useState(0)const [otherCounter, setOtherCounter] = useState(0)const increment = useCallback(() => {setCount(count + 1)}, [count])const decrement = useCallback(() => {setCount(count - 1)}, [count])const incrementOtherCounter = useCallback(() => {setOtherCounter(otherCounter + 1)}, [otherCounter])functionsCounter.add(increment)functionsCounter.add(decrement)functionsCounter.add(incrementOtherCounter)return (<div><div>Count: {count}<button onClick={increment}>+</button><button onClick={decrement}>-</button></div><div>Other-Count : {otherCounter}<button onClick={incrementOtherCounter}>incrementOtherCounter</button></div></div>)}export default HooksCallBack;

Output:

useRef Hook

useRef(initialValue) is a built-in React hook that accepts one argument as the initial value and returns a reference (aka ref). A reference is an object having a special property current.

const refContainer = useRef(initialValue);

Example:

import { useRef, useState, useEffect } from 'react';function HookuseRef() {const timerIdRef = useRef(0);const [count, setCount] = useState(0);const startHandler = () => {if (timerIdRef.current) { return; }timerIdRef.current = setInterval(() => setCount(c => c+1), 1000);};const stopHandler = () => {clearInterval(timerIdRef.current);timerIdRef.current = 0;};useEffect(() => {return () => clearInterval(timerIdRef.current);}, []);return (<div><div>Timer: {count}s</div><div><button onClick={startHandler}>Start</button><button onClick={stopHandler}>Stop</button></div></div>);}export default HookuseRef;

Output:

useMemo Hook

The useMemo is a hook used in the functional component of react that returns a memoized value. In Computer Science, memoization is a concept used in general when we don’t need to recompute the function with a given argument for the next time as it returns the cached result.

The useMemo hook is used to improve performance in our React application.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a,b]);

Example:

import React, {useState} from 'react';function UseMemoHook() {const [number, setNumber] = useState(0)const squaredNum =  squareNum(number);const [counter, setCounter] = useState(0);const onChangeHandler = (e) => {setNumber(e.target.value);}const counterHander = () => {setCounter(counter + 1);}return (<div className="App"><input type="number" placeholder="Enter a number"value={number} onChange={onChangeHandler}></input><div>Square Of {number}: {squaredNum}</div><button onClick= {counterHander}>Counter</button><div>Counter Of {number}: {counter}</div></div>);}function squareNum(number){console.log("Squaring will be done!");return Math.pow(number, 2);}export default UseMemoHook;

Output:

useLayoutEffect Hook

The useLayoutEffect works similarly to useEffect but rather working asynchronously like useEffect hook, it fires synchronously after all DOM loading is done loading. This is useful for synchronously re-rendering the DOM and also to read the layout from the DOM.

The useLayoutEffect hook works in the same phase as componentDidMount and componentDidUpdate methods. We should only use useLayoutEffect if useEffect isn’t outputting the expected result.

Example:

import React, { useLayoutEffect, useState } from 'react';function UseEffectlayoutHooks() {const [value, setValue] = useState('ABC');useLayoutEffect(() => {if (value === "ABC") {//State ChangesetValue("Udemy");}console.log("UseLayoutEffect is called with the value of ", value);}, [value]);return <div>{value} is the greatest portal for learning new things.</div>;}export default UseEffectlayoutHooks;

Output:

useDebugValue Hook

This hook provides custom labels to custom hooks so as to make the process of debugging easier and efficient. It is only called when the React Developer tools are toggled on.

useDebugValue(value,()=>{})

Example:

function useDebugStatus(friendID) {
const [value, setValue] = useState(null);
useDebugValue(value ? Not Empty : Empty);
return value;
}

toDateString function unnecessarily by passing the following formatter:

useDebugValue(date, date => date.toDateString());

useImperativeHandle Hook

useImperativeHandle and useRef hook allows to pass the ref object but the latter one doesn’t allow to customize the instances that are also passed with the ref object. useImperativeHandle hooks is different from the useRef hook in majorly two ways :

  • It allows handling and customizing the returned value explicitly.
  • It allows you to replace the native instances of the ref object with the user-defined ones.

useImperativeHandle(ref, createHandle, [deps])

Example:

UseImperative.js

import React, { useRef, useImperativeHandle, forwardRef } from 'react';function UseImperative(props, ref) {const btn = useRef();useImperativeHandle(ref, () => ({focus: () => {console.log('Input is in focus');},}));return <input ref={btn} {...props} placeholder="Type Here" />;}export default forwardRef(UseImperative);

UseimperativeApp.js

import React, { useRef } from 'react';import UseImperative from './UseImperative';function UseimperativeApp () {const inputRef = useRef(null);return (<div><UseImperative onFocus={() => inputRef.current.focus()}ref={inputRef} /></div>);}export default UseimperativeApp;

Output:

--

--