SDKs

React

React apps use @flagbearer/web with two small hooks. Read the Web SDK page for install, keys, users and defaults.

One client, outside render

Create the client once, in its own module, not inside a component. Then read flags with React's external-store hook:

// src/flags.ts
import { useEffect, useSyncExternalStore } from "react";

import { init, type FlagKey } from "@flagbearer/web";

export const flags = init({ clientKey: "fbc_..." });

// FlagKey checks keys against the file from `generate types`, described on the
// Web SDK page.
export function useFlag(key: FlagKey, defaultValue: boolean) {
  const enabled = useSyncExternalStore(
    flags.subscribe,
    () => flags.getSnapshot()[key] ?? defaultValue,
    () => defaultValue,
  );

  useEffect(() => {
    flags.isEnabled(key, defaultValue);
  }, [key, defaultValue, enabled]);

  return enabled;
}

// False until the current user's flags have loaded.
export function useFlagsLoaded() {
  return useSyncExternalStore(
    flags.subscribe,
    () => flags.getStatus() !== "loading",
    () => false,
  );
}

Users

When the signed-in user is known or changes, call identify, for example in the component that loads the session:

useEffect(() => {
  if (user) flags.identify({ key: user.id, email: user.email });
}, [user?.id]);

The email is optional. Include it to turn flags on for testers by email.

Checking a flag

const newCheckout = useFlag("new-checkout", false);
return newCheckout ? <NewCheckout /> : <Checkout />;
  • Defaults. Pass the value the app should use before flags load.

  • No flash. Use useFlagsLoaded to hold back UI that mustn't switch between the default and the real value:

    const loaded = useFlagsLoaded();
    const newCheckout = useFlag("new-checkout", false);
    if (!loaded) return <Spinner />;
    return newCheckout ? <NewCheckout /> : <Checkout />;

Server rendering and hydration

During server rendering and hydration, useFlag returns the default and useFlagsLoaded returns false, so there are no hydration mismatches. The real values take over once the client's flags load. Importing the flags module during server rendering is safe.