Skip to content

Conversation

@yugisu-flux
Copy link

@yugisu-flux yugisu-flux commented Jan 20, 2026

Motivation

This PR fixes #1331

Changes

  • Update attachHandlersAndResolve to always attach the ProviderEvents.READY listener to the client independently of the initial state.
  • Add a test for the scenario listed in the associated issue.

@yugisu-flux yugisu-flux requested review from a team as code owners January 20, 2026 14:35
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @yugisu-flux, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the robustness of feature flag evaluation within the React SDK by modifying the useFeatureFlag hook. The change ensures that the Ready event listener for the OpenFeature client is consistently attached, thereby guaranteeing that flag evaluations are correctly updated when a provider becomes available, even in complex scenarios involving asynchronous provider setup or concurrent context changes. This resolves a potential race condition and improves the reliability of flag resolution in dynamic application environments.

Highlights

  • Unconditional Ready Listener Attachment: The ProviderEvents.Ready handler is now always registered within the useFeatureFlag hook, regardless of the current provider status. This ensures that flag evaluations are updated upon provider initialization, even if the provider is already in a READY state (e.g., from a NoOp provider).
  • Dependency Array Refinement: The status variable has been removed from the useEffect dependency array in use-feature-flag.ts, as its conditional usage for attaching the Ready handler is no longer present.
  • Race Condition Test Case: A new test case has been added to evaluation.spec.tsx to specifically address and prevent a race condition where setContext is called before setProvider, ensuring that flag values are correctly updated once the provider initializes asynchronously.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@yugisu-flux yugisu-flux changed the title Attach Ready listener independent of current client status in attachHandlersAndResolve fix: attach Ready listener independent of current client status in attachHandlersAndResolve (closes #1331) Jan 20, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly addresses a race condition by ensuring the Ready event listener is always attached in attachHandlersAndResolve, regardless of the client's initial status. This prevents components from failing to update when a new provider is set. The removal of status from the useEffect dependency array is a logical consequence of this change. The new test case effectively validates this fix by simulating the specific race condition. I have one minor suggestion to improve the clarity of the new test.

Comment on lines +1143 to +1151
resolveBooleanEvaluation() {
return { value: false };
}
resolveNumberEvaluation() {
return { value: 42 };
}
resolveObjectEvaluation<T>(_: string, __: T) {
return { value: {} as T };
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For improved clarity and conciseness, you could remove the unused resolve... methods from this test-specific CustomProvider. Since the test only evaluates a string flag, only resolveStringEvaluation is necessary. This would make the provider's purpose more focused and the test easier to understand.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While these changes could indeed improve readability, they will break the Provider interface requirement in the OpenFeature.setProvider call later on. These methods are kept as slim as possible so they don't really mess with the test's readability.

…HandlersAndResolve`

Signed-off-by: Dmytrii Puzyr <dmytrii.puzyr@datadoghq.com>
@yugisu-flux yugisu-flux force-pushed the fix/use-flag-not-tracking-provider-change branch from 67bf273 to a61af23 Compare January 20, 2026 15:03
Copy link
Member

@lukas-reining lukas-reining left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me and I do not see real negative consequences.
Thanks for bringing up the issue and fixing it @yugisu-flux!
Let's wait for @toddbaert before merging.

}
// Always register the Ready handler to catch provider initialization
// even if current status is already READY (e.g., from a NoOp provider)
client.addHandler(ProviderEvents.Ready, updateEvaluationDetailsCallback, { signal: controller.signal });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is okay as updateEvaluationDetailsCallback checks the flag details for equality.
So even if the provider renders as ready and the handler triggers, only one render should be done.
Or am I overlooking anything @toddbaert?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Bad handling of a race condition between setContext and setProvider in React SDK

2 participants