React Router 7 with Vite
React Router is a standard library for routing in React applications that enables dynamic, client-side routing. This document explains how to integrate Flagship feature flag management with React Router 7 in a Vite-powered React application.
Project Overview
This project demonstrates how to integrate Flagship feature flagging system with a React Router 7 application. The integration allows you to:
Toggle features based on Flagship flags
Send analytics hits to track user behavior
Display different UI components based on feature flags
Route between different pages with flag-controlled behavior
Setup and Configuration
1. Flagship Provider Setup
The application uses a custom FsProvider
component from FsProvider.tsx to initialize Flagship with your environment credentials:
// helpers/FsProvider.tsx
import FlagshipProvider, {
LogLevel,
type VisitorData,
} from "@flagship.io/react-sdk";
import { Loader } from "../components/Loader";
export function FsProvider({
children,
visitorData
}: {
children: React.ReactNode;
visitorData?: VisitorData;
}) {
return (
<FlagshipProvider
envId={import.meta.env.VITE_ENV_ID} // Environment ID from Flagship
apiKey={import.meta.env.VITE_API_KEY} // API Key from Flagship
logLevel={LogLevel.DEBUG}
visitorData={visitorData || null} // visitor data to pass
loadingComponent={<Loader />} // Optional Loading component while flags are being fetched
>
{children}
</FlagshipProvider>
);
}
2. Application Structure
The main application structure in App.tsx sets up React Router and wraps everything in the Flagship provider:
// App.tsx
import { useState } from "react";
import { createBrowserRouter, RouterProvider } from "react-router";
import Home from "./routes/home";
import { FsProvider } from "./helpers/FsProvider";
import AnotherPage from "./routes/anotherPage";
import { Layout } from "./Layout";
const router = createBrowserRouter([
{
path: "/",
Component: Layout,
children: [
{
index: true,
Component: Home,
},
{
path: "another-page",
Component: AnotherPage,
},
],
},
]);
function App() {
// Initialize visitor data
const [visitorData, setVisitorData] = useState({
hasConsented: true,
});
return (
<FsProvider
visitorData={visitorData}
>
<RouterProvider router={router} />
</FsProvider>
);
}
3. Layout Component
The application uses a common layout with navigation in Layout.tsx:
// Layout.tsx
import { Outlet } from "react-router";
import Nav from "./components/Nav";
export function Layout() {
return (
<div className={"container"}>
<div className="nav">
<Nav />
</div>
<main className={"main"}>
<Outlet />
</main>
</div>
);
}
4. Navigation Component
The navigation component in Nav.tsx uses React Router's Link
component:
// components/Nav.tsx
import { Link } from "react-router";
export default function Nav() {
return (
<>
<Link to="/">Home</Link>
<Link to="/another-page">Page - 2</Link>
</>
);
}
Using Flagship Flags
There are two main ways to access feature flags in your components:
Option 1: Use the useFsFlag
Hook Directly
useFsFlag
Hook DirectlyAs shown in anotherPage.tsx:
// routes/anotherPage.tsx
import { useFsFlag } from "@flagship.io/react-sdk";
export default function AnotherPage() {
// Get the flag `btnColor` using useFsFlag hook
const flag = useFsFlag("btnColor");
const flagValue = flag.getValue("#dc3545");
return (
<>
<h1>This is another page</h1>
<p>flag key: btnColor</p>
<p>flag value: {flagValue}</p>
<button style={{ background: flagValue }}>Click me</button>
</>
);
}
Option 2: Create Reusable Flag Components
For better reusability, create dedicated components like MyFlagComponent.tsx:
// components/MyFlagComponent.tsx
import { useFsFlag } from "@flagship.io/react-sdk";
export function MyFlagComponent() {
// Replace 'my_flag_key' with the actual key of the flag you want to use
const myFlag = useFsFlag("my_flag_key");
return <p>flag value: {myFlag.getValue("default-value")}</p>
}
Then use this component in your routes like home.tsx:
// routes/home.tsx
import { MyFlagComponent } from "../components/MyFlagComponent";
import { MyButtonSendHit } from "../components/MyButtonSendHit";
export default function Home() {
return (
<>
<h1>Example of Flagship implementation with React Router framework</h1>
<p>flag key: my_flag_key</p>
<MyFlagComponent />
<MyButtonSendHit />
</>
);
}
Sending Analytics Hits
To track user actions, you can send analytics hits using the Flagship SDK as shown in MyButtonSendHit.tsx:
// components/MyButtonSendHit.tsx
import { useFlagship, HitType, EventCategory } from "@flagship.io/react-sdk";
export function MyButtonSendHit() {
const fs = useFlagship();
const onSendHitClick = () => {
// This will send a hit to Flagship
fs.sendHits({
type: HitType.EVENT,
category: EventCategory.ACTION_TRACKING,
action: "click button",
});
};
return (
<button
style={{ width: 100, height: 50 }}
onClick={() => {
onSendHitClick();
}}
>
Send hits
</button>
);
}
Handling Loading States
The application includes a loading component in Loader.tsx that displays while Flagship flags are being fetched:
// components/Loader.tsx
export function Loader() {
return (
<div className='loader'>
<div className="lds-ring"><div></div><div></div><div></div><div></div></div>
</div>
)
}
Environment Configuration
For Flagship to work properly, you need to set up the following environment variables in a .env.local file:
VITE_ENV_ID=your-flagship-environment-id
VITE_API_KEY=your-flagship-api-key
Running the Application
To run the application:
# Install dependencies
yarn install
# Start development server
yarn dev
# Build for production
yarn build
# Preview production build
yarn preview
Additional Considerations
Visitor Data: You can customize the visitor data passed to Flagship in the
FsProvider
component.Default Values: Always provide default values for flags in case they can't be retrieved from Flagship.
Error Handling: Consider adding error boundaries around components that depend on feature flags.
Performance: Be mindful of how many flag lookups you're performing in frequently re-rendered components.
For more information about Flagship, refer to the official documentation.
Last updated
Was this helpful?