Loading lessons...
Memoizing Functions with useCallback
Memoizing Functions with useCallback
In JavaScript, functions are first-class objects. Every time a functional component renders, any inline functions defined inside it are re-created as brand new function instances in memory.
function Parent() {
// Brand new function created in memory on EVERY render of Parent!
const handleClick = () => console.log("Clicked");
return <ReactMemoChild onClick={handleClick} />;
}
Because handleClick gets a new memory reference on every render, passing it to a React.memo child component causes shallow comparison to fail, forcing the child to re-render unnecessarily.
What is useCallback?
The useCallback hook caches (memoizes) a function instance between renders. It returns the exact same function memory reference until its dependencies change.
import { useState, useCallback } from 'react';
import React from 'react';
const ChildButton = React.memo(function ChildButton({ onClick, label }) {
console.log("ChildButton " + label + " rendered");
return <button onClick={onClick}>{label}</button>;
});
function ParentContainer() {
const [count, setCount] = useState(0);
// useCallback maintains identical function reference across renders
const handleChildClick = useCallback(() => {
console.log("Child button clicked!");
}, []); // Empty deps = stable function reference forever
return (
<div>
<p>Parent count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment Parent</button>
{/* ChildButton will NOT re-render when parent count changes! */}
<ChildButton onClick={handleChildClick} label="Submit" />
</div>
);
}
useCallback vs useMemo
useMemo(() => fn, deps): Caches the return value of executingfn().useCallback(fn, deps): Caches the function instancefnitself.
// These two lines are functionally identical:
useCallback(fn, deps);
useMemo(() => fn, deps);
Summary & TL;DR
- Components re-create local function instances on every render.
useCallback(fn, [deps])maintains a stable function memory reference across renders.- Essential when passing callback functions as props to memoized child components (
React.memo).