# 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 a 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 = {
        "show-characters": false
    };

    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.

# Use fake clients

To support a variety of development scenarios, "fake" implementations of the LaunchDarkly SDK client are available. To simulate a LaunchDarkly environment, use either InMemoryLaunchDarklyClient or LocalStorageLaunchDarklyClient.

# Toggle feature flags

Both fake implementations support toggling feature flags. To do so, first ensure that the client is an editable implementation by using the isEditableLaunchDarklyClient utility function. Then, call the setFeatureFlags method of the editable client to update the feature flag values:

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

const featureFlags = {
    "show-characters": true,
    "render-summary": true
};

const client = new InMemoryLaunchDarklyClient(featureFlags);

client.setFeatureFlags({
    "show-characters": true,
    "render-summary": false
});