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 | 35x 35x 35x 2x 35x 35x 35x 24x 22x 2x 35x 20x 35x 35x | import React, { PropsWithChildren, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { start } from './FingerprintClient'
import { FingerprintContext } from './FingerprintContext'
import type { GetOptions, StartOptions } from './types'
import { deepEqual } from './utils'
import { usePromiseStore } from './usePromiseStore'
/**
* Provides the {@link FingerprintContext} to its child components.
*
* Applications should create only one client: either through a single `FingerprintProvider`
* at the root of the component tree or through the API client (`start()`). Creating another
* client will overwrite the underlying native client of the previous one.
*
* @group Hooks approach
*
* @example
* ```jsx
* <FingerprintProvider
* apiKey="your-fpjs-public-api-key"
* region="eu"
* android={{ locationTimeoutMillis: 5000 }}
* >
* <MyApp />
* </FingerprintProvider>
* ```
*/
export function FingerprintProvider({ children, ...options }: PropsWithChildren<StartOptions>) {
const { doRequest } = usePromiseStore()
// `options` is a fresh object on every render (rest spread), so we cannot depend on its identity.
// Keep a stable reference that only changes when the options change by value. This also spares
// consumers from having to memoize inline object props (e.g. `android`, `web`).
const [stableOptions, setStableOptions] = useState(options)
if (!Object.is(stableOptions, options) && !deepEqual(stableOptions, options)) {
setStableOptions(options)
}
const [client, setClient] = useState(() => start(stableOptions))
const firstRenderRef = useRef(true)
useEffect(() => {
if (firstRenderRef.current) {
firstRenderRef.current = false
} else {
setClient(start(stableOptions))
}
}, [stableOptions])
const getVisitorData = useCallback(
(getOptions?: GetOptions) => {
return doRequest(() => client.get(getOptions), getOptions)
},
[client, doRequest]
)
const contextValue = useMemo(() => ({ client, getVisitorData }), [client, getVisitorData])
return <FingerprintContext.Provider value={contextValue}>{children}</FingerprintContext.Provider>
}
|