Skip to content

Commit

Permalink
chore: add js docs for context mutator hook (#1045)
Browse files Browse the repository at this point in the history
Minor refactors, but mostly adding js-doc after
#1031.

---------

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
  • Loading branch information
toddbaert authored Oct 17, 2024
1 parent ec3d967 commit def3fe8
Show file tree
Hide file tree
Showing 13 changed files with 69 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Client } from '@openfeature/web-sdk';
import React from 'react';
import type { NormalizedOptions, ReactFlagEvaluationOptions} from '../common/options';
import { normalizeOptions } from '../common/options';
import type { NormalizedOptions, ReactFlagEvaluationOptions} from '../common';
import { normalizeOptions } from '../common';

/**
* The underlying React context.
Expand Down
4 changes: 4 additions & 0 deletions packages/react/src/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './context';
export * from './is-equal';
export * from './options';
export * from './suspense';
1 change: 1 addition & 0 deletions packages/react/src/context/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './use-context-mutator';
51 changes: 51 additions & 0 deletions packages/react/src/context/use-context-mutator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useCallback, useContext, useRef } from 'react';
import type { EvaluationContext } from '@openfeature/web-sdk';
import { OpenFeature } from '@openfeature/web-sdk';
import { Context } from '../common';

export type ContextMutationOptions = {
/**
* Mutate the default context instead of the domain scoped context applied at the `<OpenFeatureProvider/>`.
* Note, if the `<OpenFeatureProvider/>` has no domain specified, the default is used.
* See the {@link https://openfeature.dev/docs/reference/technologies/client/web/#manage-evaluation-context-for-domains|documentation} for more information.
* @default false
*/
defaultContext?: boolean;
};

export type ContextMutation = {
/**
* A function to set the desired context (see: {@link ContextMutationOptions} for details).
* There's generally no need to await the result of this function; flag evaluation hooks will re-render when the context is updated.
* This promise never rejects.
* @param updatedContext
* @returns Promise for awaiting the context update
*/
setContext: (updatedContext: EvaluationContext) => Promise<void>;
};

/**
* Get function(s) for mutating the evaluation context associated with this domain, or the default context if `defaultContext: true`.
* See the {@link https://openfeature.dev/docs/reference/technologies/client/web/#targeting-and-context|documentation} for more information.
* @param {ContextMutationOptions} options options for the generated function
* @returns {ContextMutation} function(s) to mutate context
*/
export function useContextMutator(options: ContextMutationOptions = { defaultContext: false }): ContextMutation {
const { domain } = useContext(Context) || {};
const previousContext = useRef<null | EvaluationContext>(null);

const setContext = useCallback(async (updatedContext: EvaluationContext) => {
if (previousContext.current !== updatedContext) {
if (!domain || options?.defaultContext) {
OpenFeature.setContext(updatedContext);
} else {
OpenFeature.setContext(domain, updatedContext);
}
previousContext.current = updatedContext;
}
}, [domain]);

return {
setContext,
};
}
7 changes: 2 additions & 5 deletions packages/react/src/evaluation/use-feature-flag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,12 @@ import {
ProviderStatus,
} from '@openfeature/web-sdk';
import { useEffect, useRef, useState } from 'react';
import type { ReactFlagEvaluationOptions} from '../common/options';
import { DEFAULT_OPTIONS, normalizeOptions } from '../common/options';
import { suspendUntilReady } from '../common/suspense';
import { useProviderOptions } from '../provider/context';
import type { ReactFlagEvaluationOptions} from '../common';
import { DEFAULT_OPTIONS, isEqual, normalizeOptions, suspendUntilReady, useProviderOptions } from '../common';
import { useOpenFeatureClient } from '../provider/use-open-feature-client';
import { useOpenFeatureClientStatus } from '../provider/use-open-feature-client-status';
import type { FlagQuery } from '../query';
import { HookFlagQuery } from './hook-flag-query';
import { isEqual } from '../common/is-equal';

// This type is a bit wild-looking, but I think we need it.
// We have to use the conditional, because otherwise useFlag('key', false) would return false, not boolean (too constrained).
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './evaluation';
export * from './query';
export * from './provider';
export * from './context';
// re-export the web-sdk so consumers can access that API from the react-sdk
export * from '@openfeature/web-sdk';
1 change: 0 additions & 1 deletion packages/react/src/provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@ export * from './provider';
export * from './use-open-feature-client';
export * from './use-when-provider-ready';
export * from './test-provider';
export * from './use-context-mutator';
4 changes: 2 additions & 2 deletions packages/react/src/provider/provider.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Client} from '@openfeature/web-sdk';
import { OpenFeature } from '@openfeature/web-sdk';
import * as React from 'react';
import type { ReactFlagEvaluationOptions } from '../common/options';
import { Context } from './context';
import type { ReactFlagEvaluationOptions } from '../common';
import { Context } from '../common';

type ClientOrDomain =
| {
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/provider/test-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
OpenFeature
} from '@openfeature/web-sdk';
import React from 'react';
import type { NormalizedOptions } from '../common/options';
import type { NormalizedOptions } from '../common';
import { OpenFeatureProvider } from './provider';

type FlagValueMap = { [flagKey: string]: JsonValue };
Expand Down Expand Up @@ -119,4 +119,4 @@ function mixInNoop(provider: Partial<Provider> = {}) {
(provider.metadata as unknown) = { name: TEST_PROVIDER };
}
return provider;
}
}
36 changes: 0 additions & 36 deletions packages/react/src/provider/use-context-mutator.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/react/src/provider/use-open-feature-client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Context } from './context';
import { Context } from '../common';
import type { Client } from '@openfeature/web-sdk';

/**
Expand Down
6 changes: 2 additions & 4 deletions packages/react/src/provider/use-when-provider-ready.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { ProviderStatus } from '@openfeature/web-sdk';
import type { ReactFlagEvaluationOptions} from '../common/options';
import { DEFAULT_OPTIONS, normalizeOptions } from '../common/options';
import { useProviderOptions } from './context';
import { useOpenFeatureClient } from './use-open-feature-client';
import { useOpenFeatureClientStatus } from './use-open-feature-client-status';
import { suspendUntilReady } from '../common/suspense';
import type { ReactFlagEvaluationOptions} from '../common';
import { DEFAULT_OPTIONS, useProviderOptions, normalizeOptions, suspendUntilReady } from '../common';

type Options = Pick<ReactFlagEvaluationOptions, 'suspendUntilReady'>;

Expand Down
2 changes: 1 addition & 1 deletion packages/react/test/provider.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ describe('OpenFeatureProvider', () => {
}));
const GlobalComponent = ({ name }: { name: string }) => {
const flagValue = useStringFlagValue<'b' | 'a'>('globalFlagsHere', 'a');

return (
<div>
<MutateButton />
Expand Down

0 comments on commit def3fe8

Please sign in to comment.