@navinc/base-react-components
Version:
Nav's Pattern Library
98 lines (84 loc) • 3.29 kB
JavaScript
import React, { useState, useEffect, useRef, createContext, useContext, useCallback } from 'react'
import { initialize } from 'launchdarkly-js-client-sdk'
import isEqual from 'lodash.isequal'
const LaunchDarklyContext = createContext({})
export const LaunchDarklyProvider = ({ clientSideID, user, children, LoadingContent, onTimeout = () => {} }) => {
const ldclient = useRef()
const [flags, setFlags] = useState([])
const [isLoading, setIsLoading] = useState(true)
const [hasTimedOut, setHasTimedOut] = useState(false)
const [isInitialized, setIsInitialized] = useState(false)
const [lastUser, setLastUser] = useState(user)
const trackMetric = ldclient.current?.track
const whichVariation = ldclient.current?.variation
const trackOfferReferral = useCallback((offer = {}, additionalInfo = {}) => {
const { matchFactorScore, mfSource, offerCategory, offerId, rtid, order } = offer
const payload = {
matchFactorScore,
mfSource,
offerCategory,
offerId,
rtid,
order,
...additionalInfo,
}
if (ldclient.current)
ldclient.current.waitForInitialization().then(() => ldclient.current.track('offer_referral', payload))
}, [])
useEffect(() => {
setTimeout(() => {
if (isLoading) {
setIsLoading(false)
setHasTimedOut(true)
// should be a bugsnag call
onTimeout()
}
}, 500)
})
useEffect(() => {
if (user.key && clientSideID && !isInitialized && !hasTimedOut) ldclient.current = initialize(clientSideID, user)
else if (!isInitialized) console.warn('Please provide a user object and clientSideID')
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [clientSideID, user.key, isInitialized, hasTimedOut]) // This is right, we only want it to re-run when the key changes if its the object it will re-run
useEffect(() => {
if (ldclient.current && user.key && !isInitialized)
ldclient.current.waitForInitialization().then(() => {
setIsInitialized(true)
setIsLoading(false)
setFlags(ldclient.current.allFlags())
})
}, [isInitialized, user.key])
useEffect(() => {
if (!isEqual(user, lastUser) && isInitialized) {
setLastUser(user)
ldclient.current.identify(user)
ldclient.current.identify(user)
}
}, [user, lastUser, ldclient, isInitialized])
// TODO add listener for on change to update flags state
return (
<LaunchDarklyContext.Provider
value={{
flags,
isLoading,
isInitialized,
trackMetric,
trackOfferReferral,
whichVariation,
ldclient: ldclient.current,
}}
>
{isLoading && !!LoadingContent ? <LoadingContent /> : children}
</LaunchDarklyContext.Provider>
)
}
export const useLaunchDarkly = () => {
const { flags, isLoading, isInitialized, trackMetric, trackOfferReferral, whichVariation, ldclient } =
useContext(LaunchDarklyContext)
const hasProvider = !!ldclient
return { flags, isLoading, isInitialized, trackMetric, trackOfferReferral, whichVariation, ldclient, hasProvider }
}
export const withLaunchDarkly = (Component) => (props) => {
const { whichVariation } = useLaunchDarkly()
return <Component whichVariation={whichVariation} {...props} />
}