Skip to main content

All hooks

useEventCallback

Custom hook that creates a memoized event callback.


See: How to read an often-changing value from useCallback?

Parameters

  • fn: (args) => result - The callback function to be memoized.

Return Value

  • (args) => result - A memoized event callback function.

Features

  • Memoization: Optimizes performance by memoizing the callback function to avoid unnecessary re-renders.
  • Prevents Invocation During Render: Ensures the callback isn't called during rendering, preventing potential issues.
  • Error Handling: Throws an error if the callback is mistakenly invoked during rendering.
  • Strict Mode Compatibility: Works seamlessly with React's strict mode for better debugging and reliability.

Notes

Avoid using useEventCallback for callback functions that depend on frequently changing state or props.

Usage

import { useEventCallback } from './useEventCallback'

export default function Component() {
  const handleClick = useEventCallback(event => {
    // Handle the event here
    console.log('Clicked', event)
  })

  return <button onClick={handleClick}>Click me</button>
}

API

function useEventCallback(fn: (args: Args) => R): (args: Args) => R

Custom hook that creates a memoized event callback.

Parameters

NameTypeDefault valueDescription
fn(args: Args) => R-The callback function.

Returns

A memoized event callback function.

Hook

import { useCallback, useRef } from 'react'

import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect'

/**
 * Custom hook that creates a memoized event callback.
 * @template Args - An array of argument types for the event callback.
 * @template R - The return type of the event callback.
 * @param {(...args: Args) => R} fn - The callback function.
 * @returns {(...args: Args) => R} A memoized event callback function.
 * @public
 * @see [Documentation](https://usehooks-ts.com/react-hook/use-event-callback)
 * @example
 * ```tsx
 * const handleClick = useEventCallback((event) => {
 *   // Handle the event here
 * });
 * ```
 */
export function useEventCallback<Args extends unknown[], R>(
  fn: (...args: Args) => R,
): (...args: Args) => R
export function useEventCallback<Args extends unknown[], R>(
  fn: ((...args: Args) => R) | undefined,
): ((...args: Args) => R) | undefined
export function useEventCallback<Args extends unknown[], R>(
  fn: ((...args: Args) => R) | undefined,
): ((...args: Args) => R) | undefined {
  const ref = useRef<typeof fn>(() => {
    throw new Error('Cannot call an event handler while rendering.')
  })

  useIsomorphicLayoutEffect(() => {
    ref.current = fn
  }, [fn])

  return useCallback((...args: Args) => ref.current?.(...args), [ref]) as (
    ...args: Args
  ) => R
}