All files useVisitorData.ts

100% Statements 17/17
100% Branches 2/2
100% Functions 6/6
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64                                                  12x 12x   12x   4x 4x 4x 4x 2x             2x           4x   4x         12x   12x              
import { useCallback, useContext, useState } from 'react'
import { FingerprintJsProContextInterface, FingerprintJsProContext } from './FingerprintJsProContext'
import { QueryResult, VisitorQueryContext, VisitorData } from './types'
import { IdentificationError } from './errors'
 
/**
 * Use the `useVisitorData` hook in your components to perform identification requests with the FingerprintJS API.
 *
 * @example
 * ```jsx
 * const {
 *   // Request state
 *   isLoading,
 *   // Error info
 *   error,
 *   // Visitor info
 *   data,
 *   // A method to be called to initiate request
 *   getData,
 * } = useVisitorData();
 * ```
 *
 * @group Hooks approach
 */
export function useVisitorData(): VisitorQueryContext {
  const { getVisitorData } = useContext<FingerprintJsProContextInterface>(FingerprintJsProContext)
  const [state, setState] = useState<QueryResult<VisitorData, IdentificationError>>({})
 
  const getData = useCallback<VisitorQueryContext['getData']>(
    async (tags, linkedId) => {
      let result: VisitorData | null = null
      try {
        setState((state) => ({ ...state, isLoading: true }))
        result = await getVisitorData(tags, linkedId)
        setState((state) => ({
          ...state,
          data: result as VisitorData,
          isLoading: false,
          error: undefined,
        }))
      } catch (error) {
        setState((state) => ({
          ...state,
          data: undefined,
          error: error as IdentificationError,
        }))
      } finally {
        setState((state) => (state.isLoading ? { ...state, isLoading: false } : state))
      }
      return result
    },
    [getVisitorData]
  )
 
  const { isLoading, data, error } = state
 
  return {
    isLoading,
    data,
    error,
    getData,
  }
}