JAVASCRIPT

Memoizing Function References with `useCallback` for Performance

Optimize React component rendering by using `useCallback` to memoize event handlers and functions, preventing unnecessary re-renders of child components.

import React, { useState, useCallback, memo } from 'react';

// A child component that will only re-render if its props change
const ExpensiveComponent = memo(({ onClick, value }) => {
  console.log('ExpensiveComponent rendered');
  return (
    <div style={{ border: '1px dashed gray', padding: '10px', margin: '10px' }}>
      <p>Value: {value}</p>
      <button onClick={onClick}>Increment from Child</button>
    </div>
  );
});

function ParentComponent() {
  const [count, setCount] = useState(0);
  const [otherState, setOtherState] = useState(0);

  // This function reference will change on every re-render of ParentComponent
  // const handleClickWithoutCallback = () => {
  //   setCount(prevCount => prevCount + 1);
  // };

  // This function reference will only change if `setCount` changes (which it won't)
  // or if dependencies in the array change.
  const handleClickWithCallback = useCallback(() => {
    setCount(prevCount => prevCount + 1);
  }, []); // Empty dependency array means this function is memoized once

  console.log('ParentComponent rendered');

  return (
    <div>
      <h1>Parent Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment Parent Count</button>
      <button onClick={() => setOtherState(otherState + 1)}>
        Change Other State ({otherState})
      </button>
      <hr />
      <ExpensiveComponent onClick={handleClickWithCallback} value={count} />
      {/*
        If using handleClickWithoutCallback, ExpensiveComponent would re-render
        even when only otherState changes, because its 'onClick' prop
        would be a new function reference each time.
      */}
    </div>
  );
}

export default ParentComponent;
How it works: The `useCallback` hook is used to memoize functions. When passed a function and a dependency array, it returns a memoized version of the callback that only changes if one of the dependencies has changed. This is particularly useful when passing callbacks to optimized child components (e.g., those wrapped in `React.memo`), as it prevents unnecessary re-renders of those children by ensuring the prop's reference remains stable across parent renders.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs