|
7 | 7 | ProviderEvents,
|
8 | 8 | ProviderStatus,
|
9 | 9 | } from '@openfeature/web-sdk';
|
10 |
| -import { useEffect, useState } from 'react'; |
| 10 | +import { useEffect, useRef, useState } from 'react'; |
11 | 11 | import { DEFAULT_OPTIONS, ReactFlagEvaluationOptions, normalizeOptions } from '../common/options';
|
12 | 12 | import { suspendUntilReady } from '../common/suspense';
|
13 | 13 | import { useProviderOptions } from '../provider/context';
|
@@ -290,44 +290,50 @@ function attachHandlersAndResolve<T extends FlagValue>(
|
290 | 290 | resolver(client).call(client, flagKey, defaultValue, options),
|
291 | 291 | );
|
292 | 292 |
|
293 |
| - const updateEvaluationDetailsRef = () => { |
| 293 | + // Maintain a mutable reference to the evaluation details to have a up-to-date reference in the handlers. |
| 294 | + const evaluationDetailsRef = useRef<EvaluationDetails<T>>(evaluationDetails); |
| 295 | + useEffect(() => { |
| 296 | + evaluationDetailsRef.current = evaluationDetails; |
| 297 | + }, [evaluationDetails]); |
| 298 | + |
| 299 | + const updateEvaluationDetailsCallback = () => { |
294 | 300 | const updatedEvaluationDetails = resolver(client).call(client, flagKey, defaultValue, options);
|
295 | 301 |
|
296 | 302 | /**
|
297 | 303 | * Avoid re-rendering if the value hasn't changed. We could expose a means
|
298 | 304 | * to define a custom comparison function if users require a more
|
299 | 305 | * sophisticated comparison in the future.
|
300 | 306 | */
|
301 |
| - if (!isEqual(updatedEvaluationDetails.value, evaluationDetails.value)) { |
| 307 | + if (!isEqual(updatedEvaluationDetails.value, evaluationDetailsRef.current.value)) { |
302 | 308 | setEvaluationDetails(updatedEvaluationDetails);
|
303 | 309 | }
|
304 | 310 | };
|
305 | 311 |
|
306 | 312 | useEffect(() => {
|
307 | 313 | if (status === ProviderStatus.NOT_READY) {
|
308 | 314 | // update when the provider is ready
|
309 |
| - client.addHandler(ProviderEvents.Ready, updateEvaluationDetailsRef); |
| 315 | + client.addHandler(ProviderEvents.Ready, updateEvaluationDetailsCallback); |
310 | 316 | }
|
311 | 317 |
|
312 | 318 | if (defaultedOptions.updateOnContextChanged) {
|
313 | 319 | // update when the context changes
|
314 |
| - client.addHandler(ProviderEvents.ContextChanged, updateEvaluationDetailsRef); |
| 320 | + client.addHandler(ProviderEvents.ContextChanged, updateEvaluationDetailsCallback); |
315 | 321 | }
|
316 | 322 | return () => {
|
317 | 323 | // cleanup the handlers
|
318 |
| - client.removeHandler(ProviderEvents.Ready, updateEvaluationDetailsRef); |
319 |
| - client.removeHandler(ProviderEvents.ContextChanged, updateEvaluationDetailsRef); |
| 324 | + client.removeHandler(ProviderEvents.Ready, updateEvaluationDetailsCallback); |
| 325 | + client.removeHandler(ProviderEvents.ContextChanged, updateEvaluationDetailsCallback); |
320 | 326 | };
|
321 | 327 | }, []);
|
322 | 328 |
|
323 | 329 | useEffect(() => {
|
324 | 330 | if (defaultedOptions.updateOnConfigurationChanged) {
|
325 | 331 | // update when the provider configuration changes
|
326 |
| - client.addHandler(ProviderEvents.ConfigurationChanged, updateEvaluationDetailsRef); |
| 332 | + client.addHandler(ProviderEvents.ConfigurationChanged, updateEvaluationDetailsCallback); |
327 | 333 | }
|
328 | 334 | return () => {
|
329 | 335 | // cleanup the handlers
|
330 |
| - client.removeHandler(ProviderEvents.ConfigurationChanged, updateEvaluationDetailsRef); |
| 336 | + client.removeHandler(ProviderEvents.ConfigurationChanged, updateEvaluationDetailsCallback); |
331 | 337 | };
|
332 | 338 | }, []);
|
333 | 339 |
|
|
0 commit comments