@@ -18,69 +18,67 @@ import * as optimizely from '@optimizely/optimizely-sdk';
1818import { getLogger } from '@optimizely/js-sdk-logging' ;
1919
2020import { setupAutoUpdateListeners } from './autoUpdate' ;
21- import { VariableValuesObject , OnReadyResult } from './client'
21+ import { VariableValuesObject , OnReadyResult } from './client' ;
2222import { OptimizelyContext } from './Context' ;
2323
2424const useFeatureLogger = getLogger ( 'useFeature' ) ;
2525
2626type UseFeatureState = {
27- isEnabled : boolean ,
28- variables : VariableValuesObject ,
27+ isEnabled : boolean ;
28+ variables : VariableValuesObject ;
2929} ;
3030
3131type ClientReady = boolean ;
3232type DidTimeout = boolean ;
3333
3434type UseFeatureOptions = {
35- autoUpdate ?: boolean ,
36- timeout ?: number
35+ autoUpdate ?: boolean ;
36+ timeout ?: number ;
3737} ;
3838
3939type UseFeatureOverrides = {
40- overrideUserId ?: string ,
41- overrideAttributes ?: optimizely . UserAttributes ,
42- }
40+ overrideUserId ?: string ;
41+ overrideAttributes ?: optimizely . UserAttributes ;
42+ } ;
4343
4444interface UseFeature {
45- (
46- featureKey : string ,
47- options ?: UseFeatureOptions ,
48- overrides ?: UseFeatureOverrides ,
49- ) : [
50- UseFeatureState [ "isEnabled" ] ,
51- UseFeatureState [ "variables" ] ,
45+ ( featureKey : string , options ?: UseFeatureOptions , overrides ?: UseFeatureOverrides ) : [
46+ UseFeatureState [ 'isEnabled' ] ,
47+ UseFeatureState [ 'variables' ] ,
5248 ClientReady ,
5349 DidTimeout
54- ]
50+ ] ;
5551}
5652
5753/**
5854 * A React Hook that retrieves the status of a feature flag and its variables, optionally
5955 * auto updating those values based on underlying user or datafile changes.
60- *
61- * Note: The react client can become ready AFTER the timeout period.
56+ *
57+ * Note: The react client can become ready AFTER the timeout period.
6258 * ClientReady and DidTimeout provide signals to handle this scenario.
6359 */
64- export const useFeature : UseFeature = ( featureKey , options = { } , overrides = { } ) => {
60+ export const useFeature : UseFeature = ( featureKey , options = { } , overrides = { } ) => {
6561 const { isServerSide, optimizely, timeout } = useContext ( OptimizelyContext ) ;
6662 if ( ! optimizely ) {
6763 throw new Error ( 'optimizely prop must be supplied via a parent <OptimizelyProvider>' ) ;
6864 }
69- const finalReadyTimeout : number | undefined =
70- options . timeout !== undefined ? options . timeout : timeout ;
65+ const finalReadyTimeout : number | undefined = options . timeout !== undefined ? options . timeout : timeout ;
7166
7267 // Helper function to return the current values for isEnabled and variables.
73- const getCurrentValues = useCallback ( ( ) => ( {
74- isEnabled : optimizely . isFeatureEnabled ( featureKey , overrides . overrideUserId , overrides . overrideAttributes ) ,
75- variables : optimizely . getFeatureVariables ( featureKey , overrides . overrideUserId , overrides . overrideAttributes ) ,
76- } ) , [ featureKey , overrides ] ) ;
68+ const getCurrentValues = useCallback (
69+ ( ) => ( {
70+ isEnabled : optimizely . isFeatureEnabled ( featureKey , overrides . overrideUserId , overrides . overrideAttributes ) ,
71+ variables : optimizely . getFeatureVariables ( featureKey , overrides . overrideUserId , overrides . overrideAttributes ) ,
72+ } ) ,
73+ [ featureKey , overrides ]
74+ ) ;
7775
7876 // Set the initial state immediately serverSide
79- const [ data , setData ] = useState < UseFeatureState > ( ( ) => {
77+ const [ data , setData ] = useState < UseFeatureState > ( ( ) => {
8078 if ( isServerSide ) {
8179 return getCurrentValues ( ) ;
8280 }
83- return { isEnabled : false , variables : { } } ;
81+ return { isEnabled : false , variables : { } } ;
8482 } ) ;
8583
8684 const [ clientReady , setClientReady ] = useState ( isServerSide ? true : false ) ;
@@ -89,53 +87,48 @@ export const useFeature : UseFeature = (featureKey, options = {}, overrides = {}
8987 useEffect ( ( ) => {
9088 const cleanupFns : Array < ( ) => void > = [ ] ;
9189
92- optimizely . onReady ( { timeout : finalReadyTimeout } ) . then ( ( res : OnReadyResult ) => {
93- if ( res . success ) {
94- // didTimeout=false
95- useFeatureLogger . info ( `feature="${ featureKey } " successfully set for user="${ optimizely . user . id } "` ) ;
96- return ;
97- }
98- setDidTimeout ( true ) ;
99- useFeatureLogger . info (
100- `feature="${ featureKey } " could not be set before timeout of ${ finalReadyTimeout } ms, reason="${ res . reason || '' } "` ,
101- ) ;
102- // Since we timed out, wait for the dataReadyPromise to resolve before setting up.
103- return res . dataReadyPromise ! . then (
104- ( ) => {
105- useFeatureLogger . info (
106- `feature="${ featureKey } " is now set, but after timeout.` ,
107- ) ;
108- } ) ;
109- } )
110- . then ( ( ) => {
111- setClientReady ( true ) ;
112- setData ( getCurrentValues ( ) ) ;
113- if ( options . autoUpdate ) {
114- cleanupFns . push (
115- setupAutoUpdateListeners ( optimizely , 'feature' , featureKey , useFeatureLogger , ( ) => {
116- if ( cleanupFns . length ) {
117- setData ( getCurrentValues ( ) ) ;
118- }
119- } )
90+ optimizely
91+ . onReady ( { timeout : finalReadyTimeout } )
92+ . then ( ( res : OnReadyResult ) => {
93+ if ( res . success ) {
94+ // didTimeout=false
95+ useFeatureLogger . info ( `feature="${ featureKey } " successfully set for user="${ optimizely . user . id } "` ) ;
96+ return ;
97+ }
98+ setDidTimeout ( true ) ;
99+ useFeatureLogger . info (
100+ `feature="${ featureKey } " could not be set before timeout of ${ finalReadyTimeout } ms, reason="${ res . reason ||
101+ '' } "`
120102 ) ;
121- }
122- } )
123- . catch ( ( ) => {
124- /* The user promise or core client promise rejected. */
125- useFeatureLogger . error ( `Error initializing client. The core client or user promise(s) rejected.` ) ;
126- } )
103+ // Since we timed out, wait for the dataReadyPromise to resolve before setting up.
104+ return res . dataReadyPromise ! . then ( ( ) => {
105+ useFeatureLogger . info ( `feature="${ featureKey } " is now set, but after timeout.` ) ;
106+ } ) ;
107+ } )
108+ . then ( ( ) => {
109+ setClientReady ( true ) ;
110+ setData ( getCurrentValues ( ) ) ;
111+ if ( options . autoUpdate ) {
112+ cleanupFns . push (
113+ setupAutoUpdateListeners ( optimizely , 'feature' , featureKey , useFeatureLogger , ( ) => {
114+ if ( cleanupFns . length ) {
115+ setData ( getCurrentValues ( ) ) ;
116+ }
117+ } )
118+ ) ;
119+ }
120+ } )
121+ . catch ( ( ) => {
122+ /* The user promise or core client promise rejected. */
123+ useFeatureLogger . error ( `Error initializing client. The core client or user promise(s) rejected.` ) ;
124+ } ) ;
127125
128126 return ( ) => {
129- while ( cleanupFns . length ) {
127+ while ( cleanupFns . length ) {
130128 cleanupFns . shift ( ) ! ( ) ;
131129 }
132130 } ;
133131 } , [ optimizely ] ) ;
134132
135- return [
136- data . isEnabled ,
137- data . variables ,
138- clientReady ,
139- didTimeout ,
140- ] ;
133+ return [ data . isEnabled , data . variables , clientReady , didTimeout ] ;
141134} ;
0 commit comments