# Events

React to the document loading, pages rendering and the user navigating, for analytics, logging or your own UI.

## Basics

Pass callbacks to hear what the viewer is doing.

**Demo: An event log**

```tsx
import { PdfViewer } from '@kingtech/react-pdf-viewer';
import { useState } from 'react';

export default function Demo() {
  const [log, setLog] = useState<string[]>([]);
  const record = (line: string) => setLog((previous) => [line, ...previous].slice(0, 8));

  return (
    <>
      <PdfViewer
        source="/samples/multipage.pdf"
        onDocumentLoad={({ numPages, fingerprint }) =>
          record(`onDocumentLoad: ${numPages} pages, ${fingerprint.slice(0, 8)}…`)
        }
        onPageRender={({ page, scale, durationMs }) =>
          record(
            `onPageRender: page ${page} at ${Math.round(scale * 100)}% in ${Math.round(durationMs)} ms`,
          )
        }
        onPageChange={(page) => record(`onPageChange: ${page}`)}
        onScaleChange={(scale) => record(`onScaleChange: ${scale}`)}
      />
      <pre className="demo-output" aria-label="Event log">
        {log.length ? log.join('\n') : 'Waiting for events…'}
      </pre>
    </>
  );
}
```

| Callback                                                                  | Called with                                  | When                                                                                          |
| ------------------------------------------------------------------------- | -------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `onDocumentLoad`                                                          | `{ numPages, fingerprint }`                  | A document finished loading                                                                   |
| `onPageRender`                                                            | `{ page, scale, width, height, durationMs }` | A page finished rendering                                                                     |
| `onPageChange`, `onScaleChange`, `onRotationChange`, `onFullscreenChange` | the new value                                | The user or your code changed it; see [Controlled state](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/controlled-state/) |
| `onError`                                                                 | `PdfViewerError`                             | Something failed; see [Error states](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/error-states/)                         |
| `onDownload`, `onPrint`                                                   | the file, or nothing                         | Before saving or printing; return `false` to take over                                        |
| `onHttpError`                                                             | `Response`                                   | A URL source returned a non-2xx status                                                        |

`fingerprint` identifies the document's content, which is handy as a cache or analytics key. Callbacks can change between renders without reloading anything.

## Customization

Use render measurements to drive your own UI, such as a status bar.

**Demo: Show the size and render time of each page**

```tsx
import { PdfViewer, type PageRenderInfo } from '@kingtech/react-pdf-viewer';
import { useState } from 'react';

export default function Demo() {
  const [last, setLast] = useState<PageRenderInfo | null>(null);

  return (
    <>
      <p className="demo-output" role="status">
        {last
          ? `Page ${last.page}: ${Math.round(last.width)} × ${Math.round(last.height)} px, rendered in ${Math.round(last.durationMs)} ms`
          : 'Render a page to measure it.'}
      </p>
      <PdfViewer source="/samples/mixed-sizes.pdf" onPageRender={setLast} zoomReset />
    </>
  );
}
```

See the [customization guide](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/customization/).

## Advanced / escape hatch

`PdfPageCanvas` has its own `onRender` and `onError` for [headless](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/headless/) layouts.

## Limitations

- **No scroll or selection events.** The viewer does not report scroll position or text selection. Workaround: listen on the document area yourself (`.rpv-viewport`) or use `document.getSelection()` with the [text layer](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/text-layer/).
- **`onPageRender` fires often.** It fires after every render, including re-renders after zoom and resize. Workaround: debounce it before sending analytics.

## API

- [PageRenderInfo](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/api/page-render-info.md)

---

## PageRenderInfo reference

Details of a completed page render, passed to `onPageRender` and `onRender`: the page, the scale used, its size and the time it took.

### Used by

- [Events](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/events.md)

### Import

```ts
import type { PageRenderInfo } from '@kingtech/react-pdf-viewer';
```

### Properties

| Name | Type | Default | Required | Description |
| --- | --- | --- | --- | --- |
| `page` | `number` | — | Yes | The page rendered (after clamping). |
| `scale` | `number` | — | Yes | The scale actually rendered (after fitting). |
| `width` | `number` | — | Yes | Rendered CSS width in pixels. |
| `height` | `number` | — | Yes | Rendered CSS height in pixels. |
| `durationMs` | `number` | — | Yes | Time from request to completion. |

### Source

[packages/react-pdf-viewer/src/hooks/usePageRenderer.ts](https://github.com/kiralygyula92/react-pdf-viewer/blob/main/packages/react-pdf-viewer/src/hooks/usePageRenderer.ts#L32)

