> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fingerprintiq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# React Integration

Use FingerprintIQ with React hooks.

## Installation

```bash npm
npm install @fingerprintiq/js
```

```bash yarn
yarn add @fingerprintiq/js
```

```bash pnpm
pnpm add @fingerprintiq/js
```

`@fingerprintiq/js` ships a React hook at `@fingerprintiq/js/react`. Use it directly, or build your own wrapper with the patterns below.

## Using the built-in hook

For most apps, the built-in hook is enough:

```tsx
import { useFingerprintIQ } from '@fingerprintiq/js/react';

function Component() {
  const { result, loading, error, identify } = useFingerprintIQ({
    apiKey: 'fiq_live_...',
  });

  if (loading) return <p>Identifying…</p>;
  if (error) return <p>Error: {error.message}</p>;
  return <p>Visitor: {result?.visitorId} · Bot score: {result?.botProbability}</p>;
}
```

The hook:
- Instantiates the client once per component via `useRef`
- Auto-calls `identify()` on mount (pass `manual: true` to opt out)
- Exposes `loading`, `error`, and an `identify()` function for manual re-fetches
- Is safe in React Strict Mode

If you need custom lifecycle behavior, build your own wrapper using the pattern below.

## The `useFingerprintIQ` Hook

Build a reusable hook that wraps the SDK. Using `useRef` ensures the `FingerprintIQ` instance is created only once per component tree, even in React Strict Mode.

```tsx
import { useRef, useState } from 'react';
import FingerprintIQ from '@fingerprintiq/js';

interface FingerprintIQResult {
  visitorId: string;
  visitCount: number;
  confidence: number;
  botProbability: number;
  riskFactors: string[];
}

function useFingerprintIQ(apiKey: string) {
  const [result, setResult] = useState<FingerprintIQResult | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);
  const fiqRef = useRef<FingerprintIQ | null>(null);

  if (!fiqRef.current) {
    fiqRef.current = new FingerprintIQ({ apiKey });
  }

  const identify = async () => {
    setLoading(true);
    setError(null);
    try {
      const res = await fiqRef.current!.identify();
      setResult(res);
      return res;
    } catch (err) {
      setError(err as Error);
      throw err;
    } finally {
      setLoading(false);
    }
  };

  return { identify, result, loading, error };
}
```

## Usage in Components

```tsx
import { useEffect } from 'react';

function LoginPage() {
  const { identify, result, loading, error } = useFingerprintIQ(
    process.env.NEXT_PUBLIC_FIQ_API_KEY!
  );

  useEffect(() => {
    identify();
  }, []);

  if (loading) return <p>Identifying device...</p>;
  if (error) return <p>Fingerprint unavailable</p>;

  return (
    <div>
      <p>Visitor ID: {result?.visitorId}</p>
      <p>Visit count: {result?.visitCount}</p>
      {result?.botProbability > 0.5 && (
        <p>⚠️ Suspicious activity detected</p>
      )}
    </div>
  );
}
```

Call `identify()` as early as possible in the page lifecycle — ideally in a root layout or `useEffect` at the app level. This gives the SDK time to collect all signals before the user interacts with protected features.

## Context Provider Pattern

For larger applications, expose fingerprint data via React Context to avoid prop drilling:

```tsx
// contexts/FingerprintContext.tsx
import { createContext, useContext, useEffect, useRef, useState } from 'react';
import FingerprintIQ from '@fingerprintiq/js';

const FingerprintContext = createContext(null);

export function FingerprintProvider({ children, apiKey }) {
  const [fingerprint, setFingerprint] = useState(null);
  const fiqRef = useRef(null);

  useEffect(() => {
    if (!fiqRef.current) {
      fiqRef.current = new FingerprintIQ({ apiKey });
    }
    fiqRef.current
      .identify()
      .then(setFingerprint)
      .catch(console.error);
  }, [apiKey]);

  return (
    <FingerprintContext.Provider value={fingerprint}>
      {children}
    </FingerprintContext.Provider>
  );
}

export const useFingerprint = () => useContext(FingerprintContext);
```

```tsx
// app/layout.tsx or _app.tsx
import { FingerprintProvider } from '@/contexts/FingerprintContext';

export default function RootLayout({ children }) {
  return (
    <FingerprintProvider apiKey={process.env.NEXT_PUBLIC_FIQ_API_KEY}>
      {children}
    </FingerprintProvider>
  );
}
```

## With Next.js App Router

FingerprintIQ requires browser APIs and cannot run in Server Components. Mark any component using the SDK with `'use client'`.

```tsx
// components/FingerprintProvider.tsx
'use client';

import { useEffect, useRef } from 'react';
import FingerprintIQ from '@fingerprintiq/js';

export function FingerprintProvider({ children }: { children: React.ReactNode }) {
  const fiqRef = useRef<FingerprintIQ | null>(null);

  useEffect(() => {
    if (!fiqRef.current) {
      fiqRef.current = new FingerprintIQ({
        apiKey: process.env.NEXT_PUBLIC_FIQ_API_KEY!,
      });
    }
    fiqRef.current.identify().catch(console.error);
  }, []);

  return <>{children}</>;
}
```

**Advanced: Bot detection gate component**

Create a wrapper component that blocks rendering until a bot check passes:

  ```tsx
  'use client';

  import { useEffect, useState } from 'react';
  import { useFingerprint } from '@/contexts/FingerprintContext';

  export function BotGate({ children, threshold = 0.5, fallback = null }) {
    const fingerprint = useFingerprint();

    if (!fingerprint) return <div>Verifying device...</div>;
    if (fingerprint.botProbability > threshold) return fallback;
    return children;
  }

  // Usage
  <BotGate fallback={<BlockedPage />}>
    <ProtectedContent />
  </BotGate>
  ```