Shadcn Hooks

useCustomCompareEffect

A hook like useEffect but with a custom compare function

Only when the user's ID changes will the effect be triggered

Loading...

Installation

npx shadcn@latest add @hooks/use-custom-compare-effect
pnpm dlx shadcn@latest add @hooks/use-custom-compare-effect
yarn dlx shadcn@latest add @hooks/use-custom-compare-effect
bun x shadcn@latest add @hooks/use-custom-compare-effect

Copy and paste the following code into your project.

use-custom-compare-effect.ts
import { useEffect, useRef } from 'react'
import type { DependencyList, EffectCallback } from 'react'

export function useCustomCompareEffect<T extends DependencyList>(
  effect: EffectCallback,
  deps: T,
  customCompare: (a: T, b: T) => boolean,
) {
  const ref = useRef<T>(deps)

  if (!ref.current || !customCompare(ref.current, deps)) {
    ref.current = deps
  }

  useEffect(effect, ref.current)
}

API

/**
 * A hook like useEffect but with a custom compare function
 * @param effect - The effect to use
 * @param deps - The dependencies to use
 * @param customCompare - The custom compare function to use
 */
function useCustomCompareEffect<T extends DependencyList>(
  effect: EffectCallback,
  deps: T,
  customCompare: (a: T, b: T) => boolean,
): void

Notes

Important: Do not call setState methods inside the customCompare function. The compare function should be a pure function that only performs comparison logic.

// ❌ Don't do this
const compareById = (a: User[], b: User[]) => {
  const result = a[0]?.id === b[0]?.id
  setCount((prev) => prev + 1) // ❌ This will cause infinite re-renders
  return result
}

// ✅ Do this instead
const compareById = (a: User[], b: User[]) => {
  const result = a[0]?.id === b[0]?.id
  return result
}

Credits

Last updated on