Skip to content

useCallback

vinibiavatti1 edited this page Sep 28, 2026 · 2 revisions

By default, React re-creates function definitions on every render. useCallback caches a function definition between renders, returning the exact same function instance as long as its dependencies do not change.

Note: Typically used to pass stable function references to React.memo components or as useEffect dependencies.

Preventing Infinite Loops in useEffect

When a function that fetches data or performs side effects is defined inside a component, its reference changes on every render. If you pass that function directly into a useEffect dependency array without useCallback, it will trigger the effect on every render, resulting in an infinite execution loop.

import { useEffect, useCallback } from 'react';

const Component = () => {
    // Preserved function reference across re-renders
    const fetchData = useCallback(() => {
        fetch('/api').then(...);
    }, []);

    // Prevents infinite re-triggering since fetchData maintains a stable reference
    useEffect(() => {
        fetchData();
    }, [fetchData]);
};

Integration with React.memo

When passing callback functions down to child components wrapped in React.memo, regular inline functions break optimization because their reference changes on every parent render, forcing the child to re-render unnecessarily. The useCallback ensures a stable reference, allowing React.memo to properly skip re-renders when props remain unchanged.

import { useCallback, memo } from 'react';

// Child component wrapped in React.memo
const ExpensiveChild = memo(({ onClick }) => {
    return <button onClick={onClick}>Click!</button>;
});

const Parent = () => {
    // Stable reference across parent renders
    const handleClick = useCallback(() => {
        console.log('Button clicked');
    }, []);

    return (
        <ExpensiveChild onClick={handleClick} />
    );
};

Clone this wiki locally