Skip to content

The most common thing to do with a flag is decide whether a piece of UI renders at all. The <FeatureFlag> component does that declaratively, with optional fallback content for the off case. The render props receive the evaluated value:

import { FeatureFlag } from '@nebulr-group/bridge-react/flags';

<FeatureFlag flagKey="new_dashboard" defaultValue={false}>
  <NewDashboard />
</FeatureFlag>

{/* With fallback for the non-matching case: */}
<FeatureFlag
  flagKey="premium_feature"
  defaultValue={false}
  fallback={<button disabled title="Upgrade to unlock">Premium (locked)</button>}
>
  <button>Use premium feature</button>
</FeatureFlag>

Framework note: React reserves the prop name key for reconciliation and never forwards it to a component, so the flag key is passed as flagKey. children and fallback also accept plain nodes when you don’t need the evaluated value.

A fallback render prop also receives why the feature is off, so you can offer an upgrade only when an upgrade would actually turn it on:

<FeatureFlag
  flagKey="reports"
  defaultValue={false}
  fallback={(_value, { reason, feature, openUpgrade }) =>
    reason === 'plan' ? <button onClick={openUpgrade}>Upgrade to get {feature ?? 'reports'}</button> : null
  }
>
  <Reports />
</FeatureFlag>

reason is 'plan' (an upgrade alone would turn it on), 'permission' (this person’s role or privileges), 'off', 'rule', 'rollout', or undefined while the flag has not loaded. With 'plan', feature names the plan feature the rule asks for. openUpgrade() opens the upgrade dialog <BridgeProvider> mounts, naming the plans that include the feature; call it from a click — rendering a fallback never opens anything by itself. useFlag returns the same reason and feature.

For the common case, upgrade does this for you: with no fallback, a feature that is off because of the plan renders an “Upgrade to use this” button that opens the dialog, and anything else renders nothing.

<FeatureFlag flagKey="reports" defaultValue={false} upgrade>
  <Reports />
</FeatureFlag>

<FeatureFlag> takes the same per-call eval context (the identity and attributes a flag rule evaluates against) as useFlag’s third argument. Use it when the rule targets an app-specific attribute Bridge doesn’t already know (see Send context from your code):

<FeatureFlag
  flagKey="new_dashboard"
  defaultValue={false}
  context={{ attributes: { project_count: projects.length } }}
>
  <NewDashboard />
</FeatureFlag>

Since context is a plain prop, it’s reactive for free: React re-evaluates the object expression (and re-renders the flag) whenever projects.length changes.

Props:

PropTypeDefaultDescription
flagKeystring(required)The flag key
defaultValueT(required)Safe value; also sets the flag’s inferred type
contextPartial<EvalContext>(none)Per-call eval context (attributes win on collision)
childrennode or (value) => node(none)Rendered when the flag passes; a render prop receives the value
fallbacknode or (value, { reason, feature }) => node(none)Rendered when it doesn’t; a render prop receives the value and why the feature is off