diff --git a/src/hooks/index.ts b/src/hooks/index.ts index ed7088d..43ecbd1 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,3 +1,4 @@ -import useFeatureFlag from './useFeatureFlag' - -export { useFeatureFlag } +export { default as useCodeBlock } from './useCodeBlock' +export { default as useFeatureFlag } from './useFeatureFlag' +export { default as useRunningExperiments } from './useRunningExperiments' +export { default as useVariable } from './useVariable' diff --git a/src/hooks/useCodeBlock.ts b/src/hooks/useCodeBlock.ts new file mode 100644 index 0000000..b5bfc27 --- /dev/null +++ b/src/hooks/useCodeBlock.ts @@ -0,0 +1,18 @@ +import { DependencyList, useEffect } from 'react' +import { CodeBlockCallback, runCodeBlock } from '../experiments' + +/** + * Used to run the code block function if the code block variable is activated. + * If an empty array is passed as the last argument, the code block function will only run once (on mount). + * + * @param name The name of the code block variable. + * @param codeBlock A function that will run if the code block variable is activated. + * @param deps If present, effect will only activate if the values in the list change. + */ +function useCodeBlock(name: string, codeBlock: CodeBlockCallback, deps?: DependencyList) { + useEffect(() => { + runCodeBlock(name, codeBlock) + }, deps) +} + +export default useCodeBlock diff --git a/src/hooks/useRunningExperiments.ts b/src/hooks/useRunningExperiments.ts new file mode 100644 index 0000000..5c81f08 --- /dev/null +++ b/src/hooks/useRunningExperiments.ts @@ -0,0 +1,15 @@ +import { useContext } from 'react' +import { TaplyticsExperiments } from '../experiments' +import { TaplyticsContext, TaplyticsHookMetaData } from '../TaplyticsProvider' + +/** + * Return all available experiments as well as a meta data object. + */ +function useRunningExperiments(): [TaplyticsExperiments, TaplyticsHookMetaData] { + const { experiments, loading, error } = useContext(TaplyticsContext) + const metaData: TaplyticsHookMetaData = { loading, error } + + return [experiments, metaData] +} + +export default useRunningExperiments diff --git a/src/hooks/useVariable.ts b/src/hooks/useVariable.ts new file mode 100644 index 0000000..9cfc2a1 --- /dev/null +++ b/src/hooks/useVariable.ts @@ -0,0 +1,44 @@ +import { useEffect, useState } from 'react' +import { newAsyncVariable } from '../experiments' +import { TaplyticsHookMetaData } from '../TaplyticsProvider' + +/** + * Returns an array containing the variable value and a meta data object. + * This hook will run whenever the value of the variable is updated. + * + * @param name The name of the variable. + * @param defaultValue The default value of the variable. + * + * @returns An array containing the variable value and a meta data object. + */ +function useVariable(name: string, defaultValue: T): [T, TaplyticsHookMetaData] { + const [variable, setVariable] = useState(defaultValue) + + // This hook utilizes it's own meta data, as the context meta data do not apply. + const [loading, setIsLoading] = useState(false) + const [error, setError] = useState(null) + + const metaData: TaplyticsHookMetaData = { loading, error } + + useEffect(() => { + try { + setIsLoading(true) + + const subscriber = newAsyncVariable(name, defaultValue, (variableValue) => { + setIsLoading(false) + setVariable(variableValue) + }) + + return () => { + subscriber && subscriber?.remove() + } + } catch (error) { + setIsLoading(false) + setError(error) + } + }, []) + + return [variable, metaData] +} + +export default useVariable diff --git a/src/index.ts b/src/index.ts index 2e1785a..b0ecfc6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,7 @@ import { propertiesLoadedCallback, registerVariablesChangedListener, runCodeBlock, + CodeBlockCallback, TaplyticsExperiments, TaplyticsFeatureFlags, TaplyticsVariable, @@ -22,10 +23,11 @@ import { registerPushOpenedListener, registerPushReceivedListener, } from './push' -import { useFeatureFlag } from './hooks' +import { useCodeBlock, useFeatureFlag, useRunningExperiments, useVariable } from './hooks' import TaplyticsProvider from './TaplyticsProvider' export { + CodeBlockCallback, TaplyticsAndroidNotification, TaplyticsExperiments, TaplyticsFeatureFlags, @@ -52,5 +54,8 @@ export { setTaplyticsNewSessionListener, setUserAttributes, startNewSession, + useCodeBlock, useFeatureFlag, + useRunningExperiments, + useVariable, }