Skip to main content

Client-Side Usage

Import from @ops-ai/react-router-toggly/client.

RouterTogglyProvider

Hydrates automatically from loader data:

app/root.tsx
import { Outlet } from 'react-router';
import { RouterTogglyProvider } from '@ops-ai/react-router-toggly/client';

export default function App() {
return (
<RouterTogglyProvider>
<Outlet />
</RouterTogglyProvider>
);
}

With configuration

<RouterTogglyProvider
config={{
appKey: 'your-app-key',
debug: true,
}}
enableRefresh={true}
>
<Outlet />
</RouterTogglyProvider>

Specific route data

<RouterTogglyProvider routeId="root">
<Outlet />
</RouterTogglyProvider>

Feature component

Same model as the .NET <feature> tag helper: one component, negate for the off path, requirement for multi-flag gates.

import { Feature } from '@ops-ai/react-router-toggly/client';

{/* Show when enabled */}
<Feature featureKey="promo-banner">
<Promo />
</Feature>

{/* Show when disabled (negate) */}
<Feature featureKey="promo-banner" negate>
<ClassicBanner />
</Feature>

{/* Multi-flag any / all */}
<Feature featureKeys={['admin', 'ops']} requirement="any">
<AdminPanel />
</Feature>

<Feature featureKeys={['premium', 'analytics']} requirement="all">
<PremiumAnalytics />
</Feature>
PropRole
featureKeySingle flag
featureKeysMulti-flag list
requirement"all" (default) or "any" when using featureKeys
negateInvert the result (off path) — same as .NET negate="true"
renderOptional render prop (enabled) => … when you need both branches in one place
tip

Prefer paired <Feature> / <Feature … negate> over separate enabled/disabled component names. That matches Blazor <Feature Negate> and Razor <feature negate>.

Hooks

Use hooks when you need a boolean in JavaScript (class names, early returns, disabled controls) instead of wrapping JSX.

useFeature

import { useFeature } from '@ops-ai/react-router-toggly/client';

export function Toolbar() {
const showBeta = useFeature('beta-toolbar');
if (!showBeta) return null;
return <BetaToolbar />;
}

useFeatureFlags / useIdentity

import { useFeatureFlags, useIdentity } from '@ops-ai/react-router-toggly/client';

export function DebugPanel() {
const flags = useFeatureFlags();
const { identity } = useIdentity();
return (
<pre>
{identity ?? 'anonymous'}: {Object.keys(flags).join(', ')}
</pre>
);
}

useRefreshFlags

Imperative re-fetch of definitions (manual refresh control, recovery after network loss). Most screens do not need it — live updates go through the provider when enableRefresh is on.

import { useRefreshFlags } from '@ops-ai/react-router-toggly/client';

export function RefreshFlagsButton() {
const refresh = useRefreshFlags();
return (
<button type="button" onClick={() => refresh()}>
Refresh flags
</button>
);
}

Loader helpers

import {
useTogglyLoaderData,
useTogglyRouteLoaderData,
} from '@ops-ai/react-router-toggly/client';

const { data, toggly } = useTogglyLoaderData();
const route = useTogglyRouteLoaderData('root');