UNPKG

flagsmith-react

Version:

Flagsmith integration for React Single Page Applications (SPA)

195 lines (172 loc) 4.13 kB
import React from "react"; import { useCallback, useEffect, useReducer, useRef } from "react"; import PropTypes from "prop-types"; import FlagsmithContext from "./flagsmith-context"; import { reducer } from "./reducer"; import { useEventEmitter } from "./use-event-emitter"; import reactFlagsmith from "flagsmith"; const FlagsmithProvider = ({ api, environmentId, children, asyncStorage, cacheFlags, defaultFlags, preventFetch, flagsmith = reactFlagsmith, }) => { const [state, dispatch] = useReducer(reducer, { isLoading: true, isError: false, isIdentified: false, isListening: false, }); const { emit, useSubscription } = useEventEmitter(); const handleChange = useCallback((e) => emit(e), [emit]); const isInitialised = useRef(false) useEffect(() => { (async () => { if(isInitialised.current) return; isInitialised.current = true; try { await flagsmith.init({ api, environmentID: environmentId, onChange: handleChange, asyncStorage, cacheFlags, defaultFlags, preventFetch, }); dispatch({ type: "INITIALISED" }); } catch { console.log("Failed"); dispatch({ type: "ERRORED" }); } })(); }, [ environmentId, handleChange, flagsmith, asyncStorage, cacheFlags, defaultFlags, preventFetch, api, isInitialised ]); const identify = useCallback( async (identity, traits) => { let result = undefined; try { traits ? result = await flagsmith.identify(identity, traits) : result = await flagsmith.identify(identity); dispatch({ type: "IDENTIFIED" }); } catch { dispatch({ type: "UNIDENTIFIED" }); } return result; }, [flagsmith] ); const logout = useCallback(async () => { let result; try { result = await flagsmith.logout(); } finally { dispatch({ type: "UNIDENTIFIED" }); } return result; }, [flagsmith]); const startListening = useCallback( (interval = 1000) => { flagsmith.startListening(interval); dispatch({ type: "START_LISTENING" }); }, [flagsmith] ); const stopListening = useCallback(() => { flagsmith.stopListening(); dispatch({ type: "STOP_LISTENING" }); }, [flagsmith]); const hasFeature = useCallback( (key) => { return flagsmith.hasFeature(key); }, [flagsmith] ); const getValue = useCallback( (key) => { return flagsmith.getValue(key); }, [flagsmith] ); const getFlags = useCallback(async () => { return await flagsmith.getFlags(); }, [flagsmith]); const getAllFlags = useCallback( () => { return flagsmith.getAllFlags(); }, [flagsmith] ); const getTrait = useCallback( (key) => { return flagsmith.getTrait(key); }, [flagsmith] ); const setTrait = useCallback( async (key, value) => { return flagsmith.setTrait(key, value); }, [flagsmith] ); const incrementTrait = useCallback( async (key, incrementBy) => { return flagsmith.incrementTrait(key, incrementBy); }, [flagsmith] ); const setTraits = useCallback( async (traits) => { return flagsmith.setTraits(traits); }, [flagsmith] ); return ( <FlagsmithContext.Provider value={{ ...state, api, identify, hasFeature, getValue, subscribe: useSubscription, logout, startListening, stopListening, getFlags, getAllFlags, getTrait, setTrait, setTraits, incrementTrait, }} > {children} </FlagsmithContext.Provider> ); }; FlagsmithProvider.propTypes = { children: PropTypes.any, environmentId: PropTypes.string.isRequired, flagsmith: PropTypes.object, asyncStorage: PropTypes.object, cacheFlags: PropTypes.bool, defaultFlags: PropTypes.object, preventFetch: PropTypes.bool, api: PropTypes.string, }; export default FlagsmithProvider;