Skip to content

Commit 6ac4f7a

Browse files
[FSSDK-12296] review update
1 parent d2b8c8a commit 6ac4f7a

9 files changed

Lines changed: 53 additions & 56 deletions

src/hooks/index.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,10 @@
1717
export { useOptimizelyClient } from './useOptimizelyClient';
1818
export { useOptimizelyUserContext } from './useOptimizelyUserContext';
1919
export type { UseOptimizelyUserContextResult } from './useOptimizelyUserContext';
20+
export type { UseDecideConfig, UseDecideResult, UseDecideMultiResult } from './types';
2021
export { useDecide } from './useDecide';
21-
export type { UseDecideConfig, UseDecideResult } from './useDecide';
2222
export { useDecideForKeys } from './useDecideForKeys';
23-
export type { UseDecideMultiResult } from './useDecideForKeys';
2423
export { useDecideAll } from './useDecideAll';
2524
export { useDecideAsync } from './useDecideAsync';
26-
export type { UseDecideAsyncResult } from './useDecideAsync';
2725
export { useDecideForKeysAsync } from './useDecideForKeysAsync';
28-
export type { UseDecideMultiAsyncResult } from './useDecideForKeysAsync';
2926
export { useDecideAllAsync } from './useDecideAllAsync';

src/hooks/types.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright 2026, Optimizely
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import type { OptimizelyDecideOption, OptimizelyDecision } from '@optimizely/optimizely-sdk';
18+
19+
export interface UseDecideConfig {
20+
decideOptions?: OptimizelyDecideOption[];
21+
}
22+
23+
export type UseDecideResult =
24+
| { isLoading: true; error: null; decision: null }
25+
| { isLoading: false; error: Error; decision: null }
26+
| { isLoading: false; error: null; decision: OptimizelyDecision };
27+
28+
export type UseDecideMultiResult =
29+
| { isLoading: true; error: null; decisions: Record<string, never> }
30+
| { isLoading: false; error: Error; decisions: Record<string, never> }
31+
| { isLoading: false; error: null; decisions: Record<string, OptimizelyDecision> };

src/hooks/useAsyncDecision.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,21 +62,19 @@ export function useAsyncDecision<TResult>(
6262
return;
6363
}
6464

65-
// Store not ready — stay in loading
65+
// Ensure loading state (skip if already loading to avoid re-render)
66+
setAsyncState((prev) => {
67+
if (prev.isLoading) return prev;
68+
return { result: emptyResult, error: null, isLoading: true };
69+
});
70+
71+
// Store not ready — wait for config/user context
6672
if (!hasConfig || userContext === null) {
67-
setAsyncState({ result: emptyResult, error: null, isLoading: true });
6873
return;
6974
}
7075

7176
// Store is ready — fire async decision
7277
let cancelled = false;
73-
// Reset to loading before firing the async call.
74-
// If already in the initial loading state, returns `prev` as-is to
75-
// skip a redundant re-render on first mount.
76-
setAsyncState((prev) => {
77-
if (prev.isLoading && prev.error === null && prev.result === emptyResult) return prev;
78-
return { result: emptyResult, error: null, isLoading: true };
79-
});
8078

8179
execute(userContext).then(
8280
(result) => {

src/hooks/useDecide.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,10 @@
1515
*/
1616

1717
import { useEffect, useMemo, useState } from 'react';
18-
import type { OptimizelyDecideOption, OptimizelyDecision } from '@optimizely/optimizely-sdk';
19-
2018
import { useOptimizelyContext } from './useOptimizelyContext';
2119
import { useProviderState } from './useProviderState';
2220
import { useStableArray } from './useStableArray';
23-
24-
export interface UseDecideConfig {
25-
decideOptions?: OptimizelyDecideOption[];
26-
}
27-
28-
export type UseDecideResult =
29-
| { isLoading: true; error: null; decision: null }
30-
| { isLoading: false; error: Error; decision: null }
31-
| { isLoading: false; error: null; decision: OptimizelyDecision };
21+
import type { UseDecideConfig, UseDecideResult } from './types';
3222

3323
/**
3424
* Returns a feature flag decision for the given flag key.

src/hooks/useDecideAll.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ import { useEffect, useMemo, useState } from 'react';
1919
import { useOptimizelyContext } from './useOptimizelyContext';
2020
import { useProviderState } from './useProviderState';
2121
import { useStableArray } from './useStableArray';
22-
import type { UseDecideConfig } from './useDecide';
23-
import type { UseDecideMultiResult } from './useDecideForKeys';
22+
import type { UseDecideConfig, UseDecideMultiResult } from './types';
2423

2524
/**
2625
* Returns feature flag decisions for all flags.

src/hooks/useDecideAllAsync.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ import { useOptimizelyContext } from './useOptimizelyContext';
2121
import { useProviderState } from './useProviderState';
2222
import { useStableArray } from './useStableArray';
2323
import { useAsyncDecision } from './useAsyncDecision';
24-
import type { UseDecideConfig } from './useDecide';
25-
import type { UseDecideMultiAsyncResult } from './useDecideForKeysAsync';
24+
import type { UseDecideConfig, UseDecideMultiResult } from './types';
2625

2726
const EMPTY_DECISIONS = {} as Record<string, never>;
2827

@@ -35,7 +34,7 @@ const EMPTY_DECISIONS = {} as Record<string, never>;
3534
*
3635
* @param config - Optional configuration (decideOptions)
3736
*/
38-
export function useDecideAllAsync(config?: UseDecideConfig): UseDecideMultiAsyncResult {
37+
export function useDecideAllAsync(config?: UseDecideConfig): UseDecideMultiResult {
3938
const { store, client } = useOptimizelyContext();
4039
const decideOptions = useStableArray(config?.decideOptions);
4140
const state = useProviderState(store);
@@ -50,5 +49,5 @@ export function useDecideAllAsync(config?: UseDecideConfig): UseDecideMultiAsync
5049

5150
const { result, error, isLoading } = useAsyncDecision(state, client, fdVersion, EMPTY_DECISIONS, execute);
5251

53-
return { decisions: result, error, isLoading } as UseDecideMultiAsyncResult;
52+
return { decisions: result, error, isLoading } as UseDecideMultiResult;
5453
}

src/hooks/useDecideAsync.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,13 @@
1515
*/
1616

1717
import { useCallback, useEffect, useState } from 'react';
18-
import type { OptimizelyDecision, OptimizelyUserContext } from '@optimizely/optimizely-sdk';
18+
import type { OptimizelyUserContext } from '@optimizely/optimizely-sdk';
1919

2020
import { useOptimizelyContext } from './useOptimizelyContext';
2121
import { useProviderState } from './useProviderState';
2222
import { useStableArray } from './useStableArray';
2323
import { useAsyncDecision } from './useAsyncDecision';
24-
import type { UseDecideConfig } from './useDecide';
25-
26-
export type UseDecideAsyncResult =
27-
| { isLoading: true; error: null; decision: null }
28-
| { isLoading: false; error: Error; decision: null }
29-
| { isLoading: false; error: null; decision: OptimizelyDecision };
24+
import type { UseDecideConfig, UseDecideResult } from './types';
3025

3126
/**
3227
* Returns a feature flag decision for the given flag key using the async
@@ -38,7 +33,7 @@ export type UseDecideAsyncResult =
3833
* @param flagKey - The feature flag key to evaluate
3934
* @param config - Optional configuration (decideOptions)
4035
*/
41-
export function useDecideAsync(flagKey: string, config?: UseDecideConfig): UseDecideAsyncResult {
36+
export function useDecideAsync(flagKey: string, config?: UseDecideConfig): UseDecideResult {
4237
const { store, client } = useOptimizelyContext();
4338
const decideOptions = useStableArray(config?.decideOptions);
4439
const state = useProviderState(store);
@@ -58,5 +53,5 @@ export function useDecideAsync(flagKey: string, config?: UseDecideConfig): UseDe
5853

5954
const { result, error, isLoading } = useAsyncDecision(state, client, fdVersion, null, execute);
6055

61-
return { decision: result, error, isLoading } as UseDecideAsyncResult;
56+
return { decision: result, error, isLoading } as UseDecideResult;
6257
}

src/hooks/useDecideForKeys.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,10 @@
1515
*/
1616

1717
import { useEffect, useMemo, useState } from 'react';
18-
import type { OptimizelyDecision } from '@optimizely/optimizely-sdk';
19-
2018
import { useOptimizelyContext } from './useOptimizelyContext';
2119
import { useProviderState } from './useProviderState';
2220
import { useStableArray } from './useStableArray';
23-
import type { UseDecideConfig } from './useDecide';
24-
25-
export type UseDecideMultiResult =
26-
| { isLoading: true; error: null; decisions: Record<string, never> }
27-
| { isLoading: false; error: Error; decisions: Record<string, never> }
28-
| { isLoading: false; error: null; decisions: Record<string, OptimizelyDecision> };
21+
import type { UseDecideConfig, UseDecideMultiResult } from './types';
2922

3023
/**
3124
* Returns feature flag decisions for the given flag keys.

src/hooks/useDecideForKeysAsync.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,13 @@
1515
*/
1616

1717
import { useCallback, useEffect, useState } from 'react';
18-
import type { OptimizelyDecision, OptimizelyUserContext } from '@optimizely/optimizely-sdk';
18+
import type { OptimizelyUserContext } from '@optimizely/optimizely-sdk';
1919

2020
import { useOptimizelyContext } from './useOptimizelyContext';
2121
import { useProviderState } from './useProviderState';
2222
import { useStableArray } from './useStableArray';
2323
import { useAsyncDecision } from './useAsyncDecision';
24-
import type { UseDecideConfig } from './useDecide';
25-
26-
export type UseDecideMultiAsyncResult =
27-
| { isLoading: true; error: null; decisions: Record<string, never> }
28-
| { isLoading: false; error: Error; decisions: Record<string, never> }
29-
| { isLoading: false; error: null; decisions: Record<string, OptimizelyDecision> };
24+
import type { UseDecideConfig, UseDecideMultiResult } from './types';
3025

3126
const EMPTY_DECISIONS = {} as Record<string, never>;
3227

@@ -40,7 +35,7 @@ const EMPTY_DECISIONS = {} as Record<string, never>;
4035
* @param flagKeys - The feature flag keys to evaluate
4136
* @param config - Optional configuration (decideOptions)
4237
*/
43-
export function useDecideForKeysAsync(flagKeys: string[], config?: UseDecideConfig): UseDecideMultiAsyncResult {
38+
export function useDecideForKeysAsync(flagKeys: string[], config?: UseDecideConfig): UseDecideMultiResult {
4439
const { store, client } = useOptimizelyContext();
4540
const stableKeys = useStableArray(flagKeys);
4641
const decideOptions = useStableArray(config?.decideOptions);
@@ -60,5 +55,5 @@ export function useDecideForKeysAsync(flagKeys: string[], config?: UseDecideConf
6055

6156
const { result, error, isLoading } = useAsyncDecision(state, client, fdVersion, EMPTY_DECISIONS, execute);
6257

63-
return { decisions: result, error, isLoading } as UseDecideMultiAsyncResult;
58+
return { decisions: result, error, isLoading } as UseDecideMultiResult;
6459
}

0 commit comments

Comments
 (0)