Skip to content

Common Pitfalls

React: Don't pass inline object

typescript
// ❌ Bad: new object on every render
useIntentClick(callback, { threshold: 10 });

// ✅ Good: memoize options
const options = useMemo(() => ({ threshold: 10 }), []);
useIntentClick(callback, options);

React: Strict Mode double-mount

In React Strict Mode, mount/unmount happens twice in dev. The engine handles multiple destroy() calls gracefully.

Angular: Options are read once

intentClickOptions input is read in ngOnInit. Changing it later does not recreate the store.

Vue: Directive options changes

Similar to Angular: options passed to v-intent-click are read once on mount.

Ghost click not suppressed

Ghost click suppression only works within the same page. If you navigate away and back, the previous click coords are lost.

Long press fires on non-touch devices

Long press detection works on all devices. If you only want it on touch devices, detect first:

typescript
const isTouchDevice = window.matchMedia('(hover: none)').matches;
const options = {
    longPressDelay: isTouchDevice ? 500 : undefined,
    onLongPress: isTouchDevice ? handleLongPress : undefined,
};

Concurrent pointer not detected

Concurrent pointer detection requires pointerdown on document. If you have a modal with pointer-events: none on the backdrop, events won't bubble.

Not working inside iframe

If pointerdown happens inside a cross-origin iframe and pointerup outside, the cycle is broken. This is a browser security limitation.

TypeScript: useIntentClick type errors

Ensure:

  1. You're passing a generic type: useIntentClick<HTMLButtonElement>(...)
  2. Your callback type is (event: PointerEvent) => void

Event not received

Ensure the element has pointer-events: auto (not none).