# Use feature flags

To use feature flags, start by following the setup LaunchDarkly integration guide to create and initialize a LaunchDarkly SDK client instance. Once the setup is complete, the examples below cover the most common use cases.

For more details, refer to the reference documentation.

# Evaluate a feature flag in bootstrapping code

Once the LaunchDarkly SDK client is ready, feature flags can be evaluated in the bootstrapping code. To faciliate the evaluation of feature flags in non-React code, Squide offers a getFeatureFlag function:

import { getFeatureFlag } from "@squide/firefly";

// If the `enable-mixpanel` feature flag is not available, `true` will be returned.
const value = getFeatureFlag(launchDarklyClient, "enable-mixpanel", true);

# Evaluate a feature flag in React code

To evaluate a feature flag in React, use the useFeatureFlag hook:

import { useFeatureFlag } from "@squide/firefly";

// If the `show-characters` feature flag is not available, `true` will be returned.
const value = useFeatureFlag("show-characters", true);

# Register a conditionnal navigation item

To register a navigation item based on feature flags, refer to the register deferred navigation items guide.

# Setup the typings

Before evaluating feature flags, modules must augment the FeatureFlags interface with the feature flags they intend to evaluate to ensure type safety and autocompletion.

First, create a types folder in the project:

project
├── src
├────── register.tsx
├────── Page.tsx
├────── index.tsx
├────── App.tsx
├── types
├────── feature-flags.d.ts

Then create an feature-flags.d.ts file:

project/types/feature-flags.d.ts
import "@squide/firefly";

declare module "@squide/firefly" {
    interface FeatureFlags {
        // In the example above, the module only intends to evaliate the `show-characters` feature flag.
        "show-characters": boolean;
    }
}

Finally, update the project tsconfig.json to include the types folder:

project/tsconfig.json
{
    "compilerOptions": {
        "incremental": true,
        "tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json",
        "types": [
            "./types/feature-flags.d.ts"
        ]
    },
    "exclude": ["dist", "node_modules"]
}

If any other project using those environment variables must also reference the project's feature-flags.d.ts file:

project/tsconfig.json
{
    "compilerOptions": {
        "incremental": true,
        "tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json",
        "types": [
            "../another-project/types/feature-flags.d.ts"
        ]
    },
    "exclude": ["dist", "node_modules"]
}

Once configured, all feature flag hooks and functions are fully typed and support auto-completion:

Auto-completion example
Auto-completion example

# Setup with tests

If the code under test uses environment variables, the FireflyRuntime instance can be used to mock these variables.

Considering the following page:

./src/Page.tsx
import { useFeatureFlag } from "@squide/firefly";

export function Page() {
    const showCharacters = useFeatureFlag("show-characters", true);

    return (
        <>
            <h1>Page!<h1>
            {showCharacters && (
                <ul data-testid="character-list">
                    <li>Maren Holt</li>
                    <li>Theo Calder</li>
                    <li>Inez Navarro</li>
                </ul>
            )};
        </>
    );
}

The following unit test can be written to mock the value of show-characters and test the ouput of the createTelemetryClient function:

./tests/createTelemetryClient.test.tsx
import { FireflyProvider, FireflyRuntime, LaunchDarklyPlugin, InMemoryLaunchDarklyClient } from "@squide/firefly";
import {render, screen} from "@testing-library/react";
import type { ReactNode } from "react";
import { Page } from "./src/Page.tsx";
import "@testing-library/jest-dom";

test("when the \"show-characters\" feature flag is off, do not render the character list", () => {
    const featureFlags = new Map([
        ["show-characters", false]
    ] as const);

    const launchDarklyClient = new InMemoryLaunchDarklyClient(featureFlags);

    const runtime = new FireflyRuntime({
        plugins: [x => new LaunchDarklyPlugin(x, launchDarklyClient)]
    });

    render(
        <FireflyProvider runtime={runtime}>
            <Page />
        </FireflyProvider>
    );

    expect(screen.queryByTestId("character-list")).not.toBeInTheDocument();
});

# Setup with Storybook

To set up Storybook stories with feature flags, refer to the setup Storybook integration guide.