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.