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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 3x 3x 3x 3x 3x 35x 35x 35x 32x 32x 32x 32x 32x 32x 16x 10x 10x 10x 10x 10x 10x 9x 9x 1x 1x 1x 1x 10x 32x 13x 5x 32x 2x 96x 32x 3x | import { FpjsContextInterface, FpjsContext, GetDataOptions, QueryResult, VisitorQueryContext } from './fpjs-context' import { useCallback, useContext, useEffect, useState } from 'react' import { VisitorData, FingerprintJSPro } from '@fingerprintjs/fingerprintjs-pro-spa' import deepEquals from 'fast-deep-equal' import { toError } from './utils/to-error' import { assertIsTruthy } from './utils/assert-is-truthy' export type UseVisitorDataOptions<TExtended extends boolean> = GetDataOptions<TExtended> /** * @example * ```js * const { * // Request state * data, * isLoading, * error, * // A method to be called manually when the `immediate` field in the config is set to `false`: * getData, * } = useVisitorData({ extended: true }, { immediate: false }); * ``` * Use the `useVisitorData` hook in your components to perform identification requests with the FingerprintJS API. The returned object contains information about loading status, errors, and visitor. * * @param getOptions options for the `fp.get()` request * @param config config for the hook */ export function useVisitorData<TExtended extends boolean>( getOptions: UseVisitorDataOptions<TExtended> = {}, config: UseVisitorDataConfig = defaultUseVisitorDataConfig ): VisitorQueryContext<TExtended> { assertIsTruthy(getOptions, 'getOptions') const { immediate } = config const { getVisitorData } = useContext<FpjsContextInterface<TExtended>>(FpjsContext) const [currentGetOptions, setCurrentGetOptions] = useState<UseVisitorDataOptions<TExtended>>(getOptions) const [queryState, setQueryState] = useState<QueryResult<VisitorData<TExtended>>>({ isLoading: immediate, }) const getData = useCallback<VisitorQueryContext<TExtended>['getData']>( async (params = {}) => { assertIsTruthy(params, 'getDataParams') const { ignoreCache, ...getDataPassedOptions } = params try { setQueryState((state) => ({ ...state, isLoading: true })) const { ignoreCache: defaultIgnoreCache, ...getVisitorDataOptions } = currentGetOptions const getDataOptions: FingerprintJSPro.GetOptions<TExtended> = { ...getVisitorDataOptions, ...getDataPassedOptions, } const result = await getVisitorData( getDataOptions, typeof ignoreCache === 'boolean' ? ignoreCache : defaultIgnoreCache ) setQueryState((state) => ({ ...state, data: result, isLoading: false, error: undefined })) return result } catch (unknownError) { const error = toError(unknownError) error.name = 'FPJSAgentError' setQueryState((state) => ({ ...state, data: undefined, error })) throw error } finally { setQueryState((state) => (state.isLoading ? { ...state, isLoading: false } : state)) } }, [currentGetOptions, getVisitorData] ) useEffect(() => { if (immediate) { getData().catch((error) => { console.error(`Failed to fetch visitor data on mount: ${error}`) }) } }, [immediate, getData]) if (!Object.is(currentGetOptions, getOptions) && !deepEquals(currentGetOptions, getOptions)) { setCurrentGetOptions(getOptions) } const { isLoading, data, error } = queryState return { getData, isLoading, data, error, } } export interface UseVisitorDataConfig { /** * Determines whether the `getData()` method will be called immediately after the hook mounts or not */ immediate: boolean } const defaultUseVisitorDataConfig = { immediate: true } |