useEventCallback


The useEventCallback hook is a utility for creating memoized event callback functions in React applications. It ensures that the provided callback function is memoized and stable across renders, while also preventing its invocation during the render phase.

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.

Example

import { useEventCallback } from 'usehooks-ts'

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

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

Hook

import { useCallback, useRef } from 'react'

import { useIsomorphicLayoutEffect } from 'usehooks-ts'

/**
 * A hook for creating 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.
 * @see [Documentation](https://usehooks-ts.com/react-hook/use-event-callback)
 * @example
 * const handleClick = useEventCallback((event) => {
 *   // Handle the event here
 * });
 */
export function useEventCallback<Args extends unknown[], R>(
  fn: (...args: Args) => R,
): (...args: Args) => R {
  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])
}