Skip to content
Josselin Guillozet edited this page Oct 19, 2026 · 1 revision

Integrating with React uses functional components and hooks. Include the @iproov/web-sdk package in your application and render the <iproov-me> web component with your generated token.

ℹ️ Supported versions. We support any React version still receiving security patches. React publishes no support policy and patches only the latest major — see React versions — so in practice that is React 19 and above.

For Next.js integration, see the dedicated Next.js guide which covers the dynamic import pattern required for SSR frameworks.

Basic Integration

The example below uses Vite with React 19.

import { useCallback, useEffect, useState } from "react"
import "@iproov/web-sdk"
import { iProovSupport } from "@iproov/web-sdk/iProovSupport.js"

function IProovMe() {
  const [token, setToken] = useState(null)
  const [isLoading, setLoading] = useState(true)
  const [supported, setSupported] = useState(false)
  const [hasCheckedSupport, setHasCheckedSupport] = useState(false)
  const [supportChecker, setSupportChecker] = useState(null)

  // Initialise SDK and fetch token
  useEffect(() => {
    const init = async () => {
      const supportChecker = new iProovSupport()
      setSupportChecker(supportChecker)

      // Replace with your backend token endpoint
      const response = await fetch("***YOUR_BACKEND_TOKEN_ENDPOINT***", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          resource: "https://iproov.app",
          user_id: "example@example.com",
          client: "Web SDK React",
        }),
      })
      const data = await response.json()
      setToken(data.token)
      setLoading(false)
    }

    init().catch((err) => {
      setLoading(false)
      console.error(err)
    })
  }, [])

  // iOS motion permission must be triggered by a user gesture.
  // React's synthetic events don't always satisfy this requirement,
  // so we handle it explicitly via a button click.
  const requestMotionPermission = useCallback(() => {
    if (typeof DeviceMotionEvent.requestPermission === "function") {
      return DeviceMotionEvent.requestPermission()
    }
    return Promise.resolve("granted")
  }, [])

  const checkSupport = useCallback(async () => {
    if (supportChecker) {
      const { supported, granted } = await supportChecker.checkWithPermission()
      setHasCheckedSupport(true)
      setSupported(supported)
      console.log("Support:", supported, "Granted:", granted)
    }
  }, [supportChecker])

  const handleClick = useCallback(() => {
    requestMotionPermission().then((permissionState) => {
      if (permissionState === "granted") {
        checkSupport()
      }
    })
  }, [requestMotionPermission, checkSupport])

  if (isLoading) return <p>Loading...</p>
  if (!token) return <p>Error loading token</p>

  return (
    <div>
      <button onClick={handleClick}>Check Support</button>

      <iproov-me
        token={token}
        base_url="***YOUR_BASE_URL***"
        assets_url="***YOUR_ASSETS_URL***"
      >
        {/* Add any custom slots here */}
        <div slot="button">
          <button type="button">My Custom Button Text</button>
        </div>
      </iproov-me>

      {hasCheckedSupport && (
        supported ? <p>Device supported</p> : <p>Device not supported</p>
      )}
    </div>
  )
}

export default IProovMe

Key Integration Notes

iOS Motion Permission

DeviceMotionEvent.requestPermission() must be called synchronously inside the click handler, before any await. iOS and iPadOS bind the prompt to the user gesture, and awaiting anything first spends the activation, after which the call is rejected with no prompt shown. React's onClick is fine for this — the example above calls requestPermission() first and only then awaits the result.

Support Checker

The Support Checker has its own subpath, so it can be imported without loading the component:

import { iProovSupport } from "@iproov/web-sdk/iProovSupport.js"

const supportChecker = new iProovSupport()

// Basic check (no permission prompt)
const { supported, granted, is_native_bridge } = await supportChecker.check()

// Check with permission prompt
const result = await supportChecker.checkWithPermission()

Custom Slots

Pass custom slots as children of the <iproov-me> component:

<iproov-me token={token} base_url="***YOUR_BASE_URL***" assets_url="***YOUR_ASSETS_URL***">
  <div slot="ready">Ready to scan</div>
  <div slot="button">Start scanning</div>
  <div slot="passed">Verification passed!</div>
  <div slot="failed">Verification failed</div>
</iproov-me>

Assets

Set the assets_url attribute to the URL where your application serves the iProov SDK assets. Copy the required assets from node_modules/@iproov/web-sdk to your public directory. See the Serving Assets and CORS guide for details.

Clone this wiki locally