UNPKG

@flagship.io/react-sdk

Version:
179 lines (178 loc) 6.24 kB
'use client'; import { useCallback, useContext, useMemo } from 'react'; import { Flagship, FSFlagCollection } from './deps.js'; import { noVisitorMessage } from './constants.js'; import { FlagshipContext } from './FlagshipContext.js'; import { FSFlag } from './FSFlag.js'; import { deepClone, hasContextChanged, logError, logWarn } from './utils.js'; import { useLatestRef } from './hooks.js'; /** * This hook returns a flag object by its key. If no flag match the given key an empty flag will be returned. * @param key * @param defaultValue * @returns */ export const useFsFlag = (key) => { const { state } = useContext(FlagshipContext); const { visitor } = state; if (!visitor) { return new FSFlag(key, state); } return visitor.getFlag(key); }; const handleContextChange = (param) => { const { updateFunction, functionName, visitor, config } = param; if (!visitor) { logError(config, noVisitorMessage, functionName); return; } const originalContextClone = deepClone(visitor.context); updateFunction(); const updatedContext = visitor.context; if (hasContextChanged(originalContextClone, updatedContext)) { visitor.fetchFlags(); } }; export const useFlagship = () => { const { state } = useContext(FlagshipContext); const { visitor, config } = state; const visitorRef = useLatestRef(visitor); const configRef = useLatestRef(config); const stateRef = useLatestRef(state); const visitorContext = useMemo(() => ({ ...visitor?.context }), [JSON.stringify(visitor?.context)]); const fsUpdateContext = useCallback((context) => { handleContextChange({ config: configRef.current, visitor: visitorRef.current, updateFunction: () => visitorRef.current?.updateContext(context), functionName: 'updateContext' }); }, []); const fsClearContext = useCallback(() => { handleContextChange({ config: configRef.current, visitor: visitorRef.current, updateFunction: () => visitorRef.current?.clearContext(), functionName: 'cleanContext' }); }, []); const fsAuthenticate = useCallback((visitorId) => { const functionName = 'authenticate'; const currentVisitor = visitorRef.current; if (!currentVisitor) { logError(configRef.current, noVisitorMessage, functionName); return; } const originalVisitorId = currentVisitor.visitorId; currentVisitor.authenticate(visitorId); if (originalVisitorId !== visitorId) { currentVisitor.fetchFlags(); } }, []); const fsUnauthenticate = useCallback(() => { const functionName = 'unauthenticate'; const currentVisitor = visitorRef.current; if (!currentVisitor) { logError(configRef.current, noVisitorMessage, functionName); return; } const originalVisitorId = currentVisitor.visitorId; currentVisitor.unauthenticate(); if (originalVisitorId !== currentVisitor.visitorId) { currentVisitor.fetchFlags(); } }, []); const fsSendHit = useCallback((hit) => { const functionName = 'sendHit'; const currentVisitor = visitorRef.current; if (!currentVisitor) { logError(configRef.current, noVisitorMessage, functionName); return Promise.resolve(); } if (Array.isArray(hit)) { return currentVisitor.sendHits(hit); } return currentVisitor.sendHit(hit); }, []); const getFlag = useCallback((key) => { const currentVisitor = visitorRef.current; if (!currentVisitor) { return new FSFlag(key, stateRef.current); } return currentVisitor.getFlag(key); }, []); const fetchFlags = useCallback(async () => { const currentVisitor = visitorRef.current; if (!currentVisitor) { logWarn(configRef.current, noVisitorMessage, 'fetchFlags'); return Promise.resolve(); } return currentVisitor.fetchFlags(); }, []); const setConsent = useCallback((hasConsented) => { const currentVisitor = visitorRef.current; if (!currentVisitor) { logWarn(configRef.current, noVisitorMessage, 'setConsent'); return; } currentVisitor.setConsent(hasConsented); }, []); const close = useCallback(() => { return Flagship.close(); }, []); const getFlags = useCallback(() => { const currentVisitor = visitorRef.current; if (!currentVisitor) { const flags = new Map(); stateRef.current.flags?.forEach((flag, key) => { flags.set(key, new FSFlag(key, stateRef.current)); }); return new FSFlagCollection({ flags }); } return currentVisitor.getFlags(); }, []); const collectEAIEventsAsync = useCallback(async (...args) => { const currentVisitor = visitorRef.current; if (!currentVisitor) { return; } return currentVisitor.collectEAIEventsAsync(...args); }, []); return useMemo(() => ({ visitorId: visitor?.visitorId, anonymousId: visitor?.anonymousId, context: visitorContext, hasConsented: visitor?.hasConsented, sdkStatus: state.sdkStatus, flagsStatus: state.flagsStatus, setConsent, updateContext: fsUpdateContext, clearContext: fsClearContext, authenticate: fsAuthenticate, unauthenticate: fsUnauthenticate, sendHits: fsSendHit, getFlag, fetchFlags, close, getFlags, collectEAIEventsAsync }), [ visitor?.visitorId, visitor?.anonymousId, visitor?.hasConsented, visitorContext, state.sdkStatus, state.flagsStatus, setConsent, fsUpdateContext, fsClearContext, fsAuthenticate, fsUnauthenticate, fsSendHit, getFlag, fetchFlags, close, getFlags, collectEAIEventsAsync ]); };