---
title: "useScratch – Browser Hook Usage & Examples"
description: "React sensor hook that tracks scratching/dragging gestures on an element with mouse and touch support."
canonical: https://reactuse.com/browser/usescratch/
---

# useScratch

React sensor hook that tracks scratching/dragging gestures on an element with mouse and touch support.

`useScratch` tracks mouse and touch drag gestures on a target element, returning detailed state including `isScratching`, position coordinates (`x`, `y`), deltas (`dx`, `dy`), document-level coordinates (`docX`, `docY`), element dimensions, and timing information. It supports callbacks for scratch start, ongoing scratch, and scratch end events. This is useful for building drawing, swiping, or gesture-driven interactions.

### When to Use

- Building drawing or signature pads that track pointer movement within an element
- Implementing swipe gestures for cards, carousels, or dismissible elements
- Creating interactive scratch-off or reveal-on-drag effects

### Notes

- **SSR-safe**: Returns a default state with `isScratching: false` and undefined coordinates during server-side rendering. No event listeners are attached on the server.
- **Mouse and touch**: Handles both `mousedown`/`mousemove`/`mouseup` and `touchstart`/`touchmove`/`touchend` events for cross-device compatibility.
- **Related hooks**: See also `useMouse` for general cursor tracking and `useLongPress` for press-and-hold detection.

## Usage

```tsx live
function Demo() {
  const elementRef = useRef(null);
  const state = useScratch(elementRef, {
    onScratchStart: (s) => {
      console.log('Scratch started:', s);
    },
    onScratch: (s) => {
      console.log('Scratching:', s);
    },
    onScratchEnd: (s) => {
      console.log('Scratch ended:', s);
    },
  });

  return (
    <div style={{ padding: '20px' }}>
      <div
        ref={elementRef}
        style={{
          width: '300px',
          height: '200px',
          border: '1px solid var(--ifm-color-emphasis-300)',
          borderRadius: '8px',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          backgroundColor: state.isScratching ? 'var(--ifm-color-emphasis-200)' : 'var(--ifm-background-surface-color)',
          color: 'var(--ifm-color-content)',
          cursor: 'pointer',
          userSelect: 'none',
        }}
      >
        {state.isScratching ? 'Scratching...' : 'Click and drag to scratch'}
      </div>
      <div style={{ marginTop: '20px', fontFamily: 'monospace', fontSize: '12px', color: 'var(--ifm-color-content)' }}>
        <div><strong>isScratching:</strong> {state.isScratching ? 'true' : 'false'}</div>
        {state.x !== undefined && <div><strong>x:</strong> {Math.round(state.x)}</div>}
        {state.y !== undefined && <div><strong>y:</strong> {Math.round(state.y)}</div>}
        {state.dx !== undefined && <div><strong>dx:</strong> {Math.round(state.dx)}</div>}
        {state.dy !== undefined && <div><strong>dy:</strong> {Math.round(state.dy)}</div>}
      </div>
    </div>
  );
};

```

%%API%%