Miscellaneous Hooks

Miscellaneous Hooks

Deep dive into some other kinds of hooks

In this article, we'll explore three hooks: useContext, useMemo, and useCallback, along with simple examples demonstrating their usage.

useContext hook:

The useContext hook allows components to consume values from the React context without having to manually pass props. Context provides a way to share values like themes, user authentication, or language preferences.

Here's a simple example -

Setting up context.js:

import { createContext } from "react";

export const counterContext = createContext(0);

Setting up components:

// App.jsx
import { useState } from 'react'
import './App.css'
import Button from './components/Button'

import { counterContext } from './context/context'

function App() {

  const [count, setCount] = useState(0)

  return (
    <>
    <counterContext.Provider value={{count, setCount}}>
      <Button />
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
      </div>
    </counterContext.Provider>
    </>
  )
}

export default App
// Button.jsx
import { useContext } from 'react'
import { counterContext } from '../context/context';

const Button = () => {

  const value = useContext(counterContext);

  return (
    <div>
      <button onClick={()=> value.setCount((count)=>count+1)}>{value.count}<div>I am a button</div></button>
    </div>
  )
}

export default Button

Output:

In this example, Button consumes the counterContext and renders a button with a counter based on the current count provided by the context. When the counter of App changes, the counter of Button changes and vice versa.

useMemo hook:

The useMemo hook is used for memoizing ( storing the result so you can use it next time instead of calculating the same thing again and again ) expensive calculations, preventing unnecessary re-renders.

Here's a simple example -

Setting up components:

// App.jsx
import { useState } from 'react'
import './App.css'
import Fibonacci from './components/Fibonacci'

function App() {

  const [number, setNumber] = useState(10)

  return (
    <>
      <div className="card">
        <input type="number" value={number} onChange={(e)=> setNumber(parseInt(e.target.value))} />
        <Fibonacci n={number} />
      </div>
    </>
  )
}

export default App
// Fibonacci.jsx
import {React, useMemo} from 'react'

const Fibonacci = ({n}) => {

    const calculateFibonacci = (num) => {
        if(num<=1)
          return num;

        return calculateFibonacci(num-1) + calculateFibonacci(num-2);
    }

    const fibonacciNumber = useMemo(() => {
        return calculateFibonacci(n);
    }, [n])

  return (
    <div>
      <h2>Fibonacci Number at index {n}:</h2>
      <p>{fibonacciNumber}</p>
    </div>
  )
}

export default Fibonacci

Output:

In this example, we have a Fibonacci component that calculates the nth Fibonacci number using recursion. We use the useMemo hook to memoize the result of the Fibonacci calculation based on the input n. This means that if n remains the same between renders, the cached result will be returned, preventing unnecessary recalculations. ( The value is recalculated from stored values if n increases, otherwise if it decreases or remains the same then the value is taken from cache )

useCallback hook:

useCallback is similar to useMemo but specifically used for memoizing functions. It memoizes a callback function and returns a memoized version of it, preventing unnecessary re-creations of the function on each render.

Here's a simple example -

Setting up components:

// App.jsx
import { useState, useCallback } from 'react'
import './App.css'
import Button from './components/Button'

function App() {

  const [count, setCount] = useState(0)

  const handleClick = useCallback(() => {
    setCount(count + 1)
  },[count])

  return (
    <>
      <div className="card">
        <Button onClick={handleClick} />
        <p>Clicked {count} times</p>
      </div>
    </>
  )
}

export default App
// Button.jsx
import React from 'react'

const Button = ({onClick}) => {

  return (
    <div>
      <button onClick={onClick}>Click me</button>
    </div>
  )
}

export default Button

Output:

In this example, handleClick is memoized using useCallback, ensuring that it remains the same function instance as long as count remains unchanged.