React Dojo

Search

Search concepts, exercises and quizzes

dom

useLongPress

Detects long presses on any element. Fires a callback after holding for the configured duration and cancels if the user releases early.


useLongPress.ts
import { useCallback, useRef } from "react"

interface UseLongPressOptions {
  delay?: number
  onStart?: () => void
  onCancel?: () => void
}

export function useLongPress(
  callback: () => void,
  { delay = 500, onStart, onCancel }: UseLongPressOptions = {}
) {
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
  const callbackRef = useRef(callback)
  const onStartRef = useRef(onStart)
  const onCancelRef = useRef(onCancel)

  callbackRef.current = callback
  onStartRef.current = onStart
  onCancelRef.current = onCancel

  const start = useCallback(() => {
    onStartRef.current?.()
    timerRef.current = setTimeout(() => {
      callbackRef.current()
      timerRef.current = null
    }, delay)
  }, [delay])

  const cancel = useCallback(() => {
    if (timerRef.current) {
      clearTimeout(timerRef.current)
      timerRef.current = null
      onCancelRef.current?.()
    }
  }, [])

  return {
    onMouseDown: start,
    onMouseUp: cancel,
    onMouseLeave: cancel,
    onTouchStart: start,
    onTouchEnd: cancel,
  }
}
Was this helpful?
Sign in to give feedback