@@ -8,7 +8,7 @@ import type {
8
8
JsonValue ,
9
9
} from '@openfeature/web-sdk' ;
10
10
import { ProviderEvents , ProviderStatus } from '@openfeature/web-sdk' ;
11
- import { useEffect , useRef , useState } from 'react' ;
11
+ import { useCallback , useEffect , useRef , useState } from 'react' ;
12
12
import {
13
13
DEFAULT_OPTIONS ,
14
14
isEqual ,
@@ -287,8 +287,7 @@ function attachHandlersAndResolve<T extends FlagValue>(
287
287
const client = useOpenFeatureClient ( ) ;
288
288
const status = useOpenFeatureClientStatus ( ) ;
289
289
const provider = useOpenFeatureProvider ( ) ;
290
-
291
- const controller = new AbortController ( ) ;
290
+ const isFirstRender = useRef ( true ) ;
292
291
293
292
if ( defaultedOptions . suspendUntilReady && status === ProviderStatus . NOT_READY ) {
294
293
suspendUntilInitialized ( provider , client ) ;
@@ -298,17 +297,30 @@ function attachHandlersAndResolve<T extends FlagValue>(
298
297
suspendUntilReconciled ( client ) ;
299
298
}
300
299
301
- const [ evaluationDetails , setEvaluationDetails ] = useState < EvaluationDetails < T > > (
300
+ const [ evaluationDetails , setEvaluationDetails ] = useState < EvaluationDetails < T > > ( ( ) =>
302
301
resolver ( client ) . call ( client , flagKey , defaultValue , options ) ,
303
302
) ;
303
+
304
+ // Re-evaluate when dependencies change (handles prop changes like flagKey), or if during a re-render, we have detected a change in the evaluated value
305
+ useEffect ( ( ) => {
306
+ if ( isFirstRender . current ) {
307
+ isFirstRender . current = false ;
308
+ return ;
309
+ }
310
+
311
+ const newDetails = resolver ( client ) . call ( client , flagKey , defaultValue , options ) ;
312
+ if ( ! isEqual ( newDetails . value , evaluationDetails . value ) ) {
313
+ setEvaluationDetails ( newDetails ) ;
314
+ }
315
+ } , [ client , flagKey , defaultValue , options , resolver , evaluationDetails ] ) ;
304
316
305
317
// Maintain a mutable reference to the evaluation details to have a up-to-date reference in the handlers.
306
318
const evaluationDetailsRef = useRef < EvaluationDetails < T > > ( evaluationDetails ) ;
307
319
useEffect ( ( ) => {
308
320
evaluationDetailsRef . current = evaluationDetails ;
309
321
} , [ evaluationDetails ] ) ;
310
322
311
- const updateEvaluationDetailsCallback = ( ) => {
323
+ const updateEvaluationDetailsCallback = useCallback ( ( ) => {
312
324
const updatedEvaluationDetails = resolver ( client ) . call ( client , flagKey , defaultValue , options ) ;
313
325
314
326
/**
@@ -319,15 +331,19 @@ function attachHandlersAndResolve<T extends FlagValue>(
319
331
if ( ! isEqual ( updatedEvaluationDetails . value , evaluationDetailsRef . current . value ) ) {
320
332
setEvaluationDetails ( updatedEvaluationDetails ) ;
321
333
}
322
- } ;
334
+ } , [ client , flagKey , defaultValue , options , resolver ] ) ;
323
335
324
- const configurationChangeCallback : EventHandler < ClientProviderEvents . ConfigurationChanged > = ( eventDetails ) => {
325
- if ( shouldEvaluateFlag ( flagKey , eventDetails ?. flagsChanged ) ) {
326
- updateEvaluationDetailsCallback ( ) ;
327
- }
328
- } ;
336
+ const configurationChangeCallback = useCallback < EventHandler < ClientProviderEvents . ConfigurationChanged > > (
337
+ ( eventDetails ) => {
338
+ if ( shouldEvaluateFlag ( flagKey , eventDetails ?. flagsChanged ) ) {
339
+ updateEvaluationDetailsCallback ( ) ;
340
+ }
341
+ } ,
342
+ [ flagKey , updateEvaluationDetailsCallback ] ,
343
+ ) ;
329
344
330
345
useEffect ( ( ) => {
346
+ const controller = new AbortController ( ) ;
331
347
if ( status === ProviderStatus . NOT_READY ) {
332
348
// update when the provider is ready
333
349
client . addHandler ( ProviderEvents . Ready , updateEvaluationDetailsCallback , { signal : controller . signal } ) ;
@@ -348,7 +364,14 @@ function attachHandlersAndResolve<T extends FlagValue>(
348
364
// cleanup the handlers
349
365
controller . abort ( ) ;
350
366
} ;
351
- } , [ ] ) ;
367
+ } , [
368
+ client ,
369
+ status ,
370
+ defaultedOptions . updateOnContextChanged ,
371
+ defaultedOptions . updateOnConfigurationChanged ,
372
+ updateEvaluationDetailsCallback ,
373
+ configurationChangeCallback ,
374
+ ] ) ;
352
375
353
376
return evaluationDetails ;
354
377
}
0 commit comments