Tutorials Logic, IN info@tutorialslogic.com

React Hooks useRef, useMemo, useCallback

Why These Hooks Matter

Once you understand useState and useEffect, advanced hooks help solve the next group of problems in React applications. They help you keep values across renders, share data deeply in the component tree, and optimize expensive calculations or repeated re-renders.

The important thing is to use each hook for the right job. useRef is not a replacement for state, useContext is not a complete state management library, and useMemo and useCallback are useful only when they solve a real performance problem.

Quick Comparison

Hook Main purpose Triggers re-render? Common use
useRef Store a mutable value across renders No DOM access, previous values, timers
useContext Read shared data from a provider Yes, when context value changes Theme, auth user, language
useMemo Memoize a calculated value No Filtering, sorting, expensive derived data
useCallback Memoize a function reference No Passing stable handlers to memoized children

useRef

useRef stores a value that stays the same between renders. Updating a ref does not re-render the component. This makes it useful for remembering values that React does not need to display directly.

The two most common uses of useRef are accessing DOM elements and storing mutable values like timer IDs or previous values.

useRef Examples

useRef Examples
import { useRef } from 'react'

function FocusInput() {
    const inputRef = useRef(null)

    const focusField = () => {
        inputRef.current.focus()
    }

    return (
        <div>
            <input ref={inputRef} placeholder="Type here" />
            <button onClick={focusField}>Focus Input</button>
        </div>
    )
}

useRef - JSX Example

useRef - JSX Example
import { useRef, useState, useEffect } from 'react'

function PreviousValue() {
    const [count, setCount] = useState(0)
    const previousCount = useRef(0)

    useEffect(() => {
        previousCount.current = count
    }, [count])

    return (
        <div>
            <p>Current: {count}</p>
            <p>Previous: {previousCount.current}</p>
            <button onClick={() => setCount(count + 1)}>Increase</button>
        </div>
    )
}

useContext

useContext lets you read shared values without passing props through many levels of components. This is useful when the same data is needed in many places, such as theme, language, or authentication details.

Context works best for shared app-level data. If the data is needed by only one or two nearby components, normal props are often simpler.

useContext Example

useContext Example
import { createContext, useContext, useState } from 'react'

const ThemeContext = createContext(null)

export function ThemeProvider({ children }) {
    const [theme, setTheme] = useState('light')

    return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
            {children}
        </ThemeContext.Provider>
    )
}

export function useTheme() {
    return useContext(ThemeContext)
}

useContext - JSX Example

useContext - JSX Example
import { useTheme } from './ThemeContext'

function Navbar() {
    const { theme, setTheme } = useTheme()

    return (
        <nav>
            <p>Current theme: {theme}</p>
            <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
                Toggle Theme
            </button>
        </nav>
    )
}

useMemo

useMemo stores the result of a calculation so React does not repeat the same expensive work on every render. It is useful when the calculation takes noticeable time or when you want to avoid recreating a derived value unnecessarily.

Do not use useMemo for every small calculation. It is best when the work is expensive enough to justify caching.

useMemo Example

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

function ProductList({ products }) {
    const [search, setSearch] = useState('')

    const filteredProducts = useMemo(() => {
        return products.filter(product =>
            product.name.toLowerCase().includes(search.toLowerCase())
        )
    }, [products, search])

    return (
        <div>
            <input
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                placeholder="Search products"
            />
            <ul>
                {filteredProducts.map(product => (
                    <li key={product.id}>{product.name}</li>
                ))}
            </ul>
        </div>
    )
}

useCallback

useCallback stores a function reference so the same function can be reused between renders. This is mainly useful when passing a callback to a memoized child component.

Without useCallback, a new function is created on every render. Sometimes that is completely fine. Use it when a stable function reference actually helps performance or avoids unnecessary child re-renders.

useCallback Example

useCallback Example
import { useState, useCallback, memo } from 'react'

const ChildButton = memo(function ChildButton({ onClick }) {
    console.log('Child rendered')
    return <button onClick={onClick}>Increment</button>
})

function Parent() {
    const [count, setCount] = useState(0)
    const [other, setOther] = useState(0)

    const handleIncrement = useCallback(() => {
        setCount(prev => prev + 1)
    }, [])

    return (
        <div>
            <p>Count: {count}</p>
            <p>Other: {other}</p>
            <ChildButton onClick={handleIncrement} />
            <button onClick={() => setOther(other + 1)}>Update Other</button>
        </div>
    )
}

How to Choose the Right Hook

Use useRef when you need to remember something without re-rendering. Use useContext when many nested components need the same shared value. Use useMemo when a calculated value is expensive to recompute. Use useCallback when a stable function reference helps a memoized child component.

Best Practices

Situation Recommended approach
You need to focus or measure a DOM element Use useRef
You need shared theme or user information Use useContext
You are repeatedly filtering or sorting a large list Use useMemo if the work is expensive
A memoized child gets a new callback every render Use useCallback
You are optimizing code before seeing a real issue Avoid premature optimization

Summary

Advanced hooks help React applications scale more cleanly. useRef remembers mutable values, useContext shares data, useMemo caches calculated values, and useCallback caches function references. Once you understand the purpose of each one, it becomes much easier to choose the right hook for the problem you are solving.

Before you move on

React Hooks useRef, useMemo, useCallback Mastery Check

5 checks
  • Once you understand useState and useEffect, advanced hooks help solve the next group of problems in React applications.
  • They help you keep values across renders, share data deeply in the component tree, and optimize expensive calculations or repeated re-renders.
  • useRef stores a value that stays the same between renders.
  • Updating a ref does not re-render the component.
  • This makes it useful for remembering values that React does not need to display directly.
Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.