Flag, Switch and Experiment
Each component is one useFlag plus a branch, so exposure is recorded the same way as a hook read. They render on the first frame: until the local snapshot loads, defaultValue decides which branch shows. They render no host element of their own and nest freely.
| Component | Shows while the flag is on | Shows while off | Unknown flag (defaultValue) |
|---|---|---|---|
<Flag> | children | fallback | off: new features stay hidden |
<Switch> | children | fallback | on: shipped features stay up |
<Experiment> | <Experiment.Variant variant="…"> | <Experiment.Variant control> | off: control |
<Flag>
Props: name, fallback? (default nothing), defaultValue? (default false), children. A feature behind a flag.
<Switch>
Same props, but defaultValue defaults to true. A kill switch around a feature that already ships: children stay up until the dashboard disables the flag, then fallback takes over. The difference from <Flag> is only the default, which fails open so a shipped feature keeps working offline.
Switch has the same name as React Native’s toggle. If a file uses both, rename one on import: import { Switch as KillSwitch } from "@gates/expo".
<Experiment>
Two arms of one flag. The assignment is made once in <Experiment> and shared through context, so every <Experiment.Variant> inside agrees, however deep or however many there are, and exposure counts once. Flags are boolean, so an experiment has exactly two arms: control (flag off) and one named variant (flag on). The name labels the code path in your source; the flag decides. The rollout percentage sets the split. Gates records exposure and adoption but does not compute statistics.
<Experiment.Variant> throws if rendered outside an <Experiment>, or without either control or variant.