Hooks in React:

Nitin SharmaNitin Sharma
5 min read
  1. useRef():

It is used to access the DOM element

It is used to create mutable variable which will not re-render the component

Syntax:

const variableName=useRef(Optional initialValue);

example:

UseReference.jsx

import React, { useEffect, useRef, useState } from 'react'

const UseReference = () => {
    const [name,setName]=useState("");
    const count=useRef(0)

    useEffect(()=>{
        count.current=count.current+1;
    });

  return (
    <div>
        <input type="text" onChange={(e)=>setName(e.target.value)} />
        <h2>Name : {name}</h2>
        <h2>Render: {count.current}</h2>
    </div>
  )
}

export default UseReference

call this in App.jsx and see the result

In react we can add ref attribute to element to access it directly

example:

UseReference2.jsx

import React, { useRef } from 'react'

const UseReference2 = () => {
    const InputEle=useRef()
    const handleClick=()=>{
        console.log(InputEle.current);
    };
  return (
    <div>
        <input type="text" ref={InputEle}/>
        <button onClick={handleClick}>Click Here</button>
    </div>
  )
}

export default UseReference2
  1. UseReducer():

  • UseReducer is used to manage complex state in react application

  • It is work like state management tool

    State management tool is used to manage all state in the application in a simple way

  • Always use the useReduce hooks when you have a lot of states and method to handle

Syntax:

const[ state, dispatch ] = useReduce("Reducer function", "Default State");

example:

UseReducer.jsx:

import React, { useReducer } from 'react'

const UseReducerHook = () => {
    const [state, dispatch] = useReducer(reducer, initialState)

    const increaseCount = () => {
        dispatch({ type: ACTION.INCREASE })
    }
    const decreaseCount = () => {
        dispatch({ type: ACTION.DECREASE })
    }
    return (
        <div>
            <h2>Count: {state.count}</h2>
            <button onClick={increaseCount}>Increase</button>
            <button onClick={decreaseCount}>Decrease</button>

        </div>
    )
}
const ACTION = {
    INCREASE: "increment",
    DECREASE: "decrement"
}
const initialState = { count: 0 }
const reducer = (state, action) => {
    switch (action.type) {
        case ACTION.INCREASE:
            return { count: state.count + 1 };
        case ACTION.DECREASE:
            return { count: state.count - 1 };
        default:
            return state;
    }

}

export default UseReducerHook

call this component in App.jsx and see the result

  1. UseLayputEffect():

  • It work same as useEffect()(same syntax too).

  • It run before the DOM is printed on the browser

  • It run Synchronously.

  • The most common use case is to get the dimension of the layout.

By this Example you will understand the use of useEffect and useLayoutEffect just uncomment the useEffect function and comment useLayoutEffect, then vise versa.

import React, { useState, useLayoutEffect, useRef } from 'react';

const UseLayoutEffect = () => {
    const [toggle, setToggle] = useState(false);
    const textRef = useRef();

    useLayoutEffect(() => {
        if (textRef.current != null) {
            const dimension = textRef.current.getBoundingClientRect();
            textRef.current.style.paddingTop = `${dimension.height}px`;
        }
    }, [toggle]);

/*
    // useEffect(() => {
    //     if (textRef.current != null) {
    //         const dimension = textRef.current.getBoundingClientRect();
    //         textRef.current.style.paddingTop = `${dimension.height}px`;
    //     }
    // }, [toggle]);
*/

    return (
        <div>
            <button onClick={() => setToggle(!toggle)}>Click</button>
            {toggle && <h4 ref={textRef}>Code for fun</h4>}
        </div>
    );
};

export default UseLayoutEffect;

call this function in on App.jsx.

But useLayputEffect() is synchronous and useEffect() is Asynchronous so most of the time we use useEffect().

And if useEffect() does not work properly then we use useLayoutEffect().

  1. useMemo():

useMemo() hook is used to apply memoization in React

What is Memoization?

Memoization is technique to improve the performance of the code and useful to avoid expensive calculations on every render when the return value is not change.

syntax:

useMemo(callback function, [dependency]);

  • In useMemo we can return and store the value in variable.

  • This improve the performance of the application

  • we can stop running unwanted function on Re-rendering.

this is the example of useMemo():

import React, { useMemo, useState } from 'react'

const UseMemoHook = () => {
    const [number,setNumber]=useState(0);
    const [dark,setDark]=useState(false);

    const doubleNumber = useMemo(() => {
        return expensiveFunction(number)
    },[number])

    const cssStyle={
        backgroundColor:dark?"black":"white",
        color:dark?"white":"black",
    };

  return (
    <div style={cssStyle}>
        <input onChange={(e)=>setNumber(e.target.valueAsNumber)}
        type='number'
        value={number}
        />
        <h2>Calculation: {doubleNumber}</h2>
        <button onClick={()=>setDark(!dark)}>Toggle</button>

    </div>
  )
}

const expensiveFunction=(num)=>{
    console.log("Loop Started");
    for(let i=0;i<100000000;i++){}
    return num;
}

export default UseMemoHook

add this component in App.jsx and see the output.

  1. useCallback():

  • It is used to return memoized function.

  • it's also useful for preventing function from being re-created on re-rendering.

  • it is same as useMemo hook the difference is useMemo return memoized value , where as useCallback return memoized function .

  • It improve rthe performance of our react application.

  • we can pass value as parameter in useCallback, where as in useMemo we can't do that.

example:

PrintTable.jsx:

import React, { useEffect, useState } from 'react'

const PrintTable = ({calculateTable}) => {
    const [ rows, setRows ]=useState([]);

    useEffect(()=>{
        console.log("Print Table Run!");
        setRows(calculateTable(2));
    },[calculateTable]);
  return rows.map((row,index)=>{
    return<p key={index}>{row}</p>;
  });
}

export default PrintTable

UseCallbackHooks.jsx:

import React, { useState, useCallback } from 'react';
import PrintTable from './PrintTable';

const UseCallbackHooks = () => {
    const [number, setNumber] = useState(1);
    const [darkTheme, setDarkTheme] = useState(false);

    const calculateTable = useCallback((value) => {
        let newNum = number + value;
        return [newNum * 1, newNum * 2, newNum * 3, newNum * 4, newNum * 5];
    }, [number]);

    const cssStyle = {
        backgroundColor: darkTheme ? "black" : "white",
        color: darkTheme ? "white" : "black",
    };

    return (
        <div style={cssStyle}>
            <input
                onChange={(e) => setNumber(e.target.valueAsNumber || 0)}
                type='number'
                value={number}
            />
            <PrintTable calculateTable={calculateTable} />
            <button onClick={() => setDarkTheme(!darkTheme)}>Click Me</button>
        </div>
    );
}

export default UseCallbackHooks;

Call UseCallbackHooks.jsx function in App.jsx and see the result.

0
Subscribe to my newsletter

Read articles from Nitin Sharma directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nitin Sharma
Nitin Sharma