/Docs

Vite + React integration

This guide assumes a Vite project using React 18 or 19 as a single-page application. By the end you'll have flag evaluation and event tracking wired into your app using @avsbhq/browser and @avsbhq/react. No server-side rendering is required.

1

Install

bash
1npm install @avsbhq/browser@^1 @avsbhq/react@^1
2

Obtain your SDK key

Open Settings > Environments in your A vs B project and copy the SDK key. For Vite, expose it via a VITE_AVSB_SDK_KEY environment variable so the build tool inlines it:

.env
bash
1VITE_AVSB_SDK_KEY=sdk_production_xxxxxxxxxxxxxxxx
Info
Vite exposes only variables prefixed with VITE_ to the browser bundle. The SDK key grants read-only flag evaluation — it is not a secret.
3

Wrap your app with AvsbProvider

Mount AvsbProvider at the root of your React tree. Pass the initial context so the SDK can evaluate flags immediately. You can update the context later with useIdentifyonce the user's identity is known.

src/main.tsx
tsx
1import React from 'react'
2import ReactDOM from 'react-dom/client'
3import { AvsbProvider } from '@avsbhq/react'
4import { App } from './App'
5
6ReactDOM.createRoot(document.getElementById('root')!).render(
7 <React.StrictMode>
8 <AvsbProvider
9 sdkKey={import.meta.env.VITE_AVSB_SDK_KEY}
10 context={{ kind: 'user', key: 'anonymous' }}
11 >
12 <App />
13 </AvsbProvider>
14 </React.StrictMode>
15)
4

Read a flag

Use useFlag in any component inside the provider. The hook returns a Flag<T> object. Access the evaluated value via .value, or use the shorthand useFlagValue to get the raw value directly.

src/components/CheckoutPage.tsx
tsx
1import { useFlag } from '@avsbhq/react'
2
3export function CheckoutPage() {
4 const checkoutV2 = useFlag('checkout-v2', false)
5
6 return checkoutV2.value ? <NewCheckout /> : <LegacyCheckout />
7}
Tip
useFlag re-renders the component when the flag value changes due to a polling update or a call to identify. Each flag subscription is independent — only components that use a changed flag re-render.
5

Track an event

src/components/PricingCard.tsx
tsx
1import { useTrack } from '@avsbhq/react'
2
3export function PricingCard({ plan }: { plan: string }) {
4 const track = useTrack()
5
6 function handleUpgrade() {
7 track('plan_upgrade', {
8 value: 49.99,
9 properties: { plan, source: 'pricing_page' },
10 })
11 }
12
13 return <button type="button" onClick={handleUpgrade}>Upgrade to {plan}</button>
14}
6

Identify a user

Call useIdentify once the user logs in. This replaces the anonymous context and rehashes all bucketing so the user receives consistent variant assignments.

src/hooks/useAuth.ts
tsx
1import { useIdentify } from '@avsbhq/react'
2
3export function usePostLoginEffect(userId: string, plan: string) {
4 const identify = useIdentify()
5
6 // Call once after the login promise resolves.
7 identify({ kind: 'user', key: userId, plan })
8}

Multi-context targeting

If your flags target organisations or devices in addition to users, pass a multi-context object:

tsx
1import { useIdentify } from '@avsbhq/react'
2
3identify({
4 kind: 'multi',
5 user: { kind: 'user', key: userId, plan: 'pro' },
6 organization: { kind: 'organization', key: orgId, tier: 'enterprise' },
7})

Graceful shutdown

AvsbProvider calls client.close() automatically when it unmounts (e.g. the React tree is torn down). In a Vite SPA this typically only happens during development hot-module replacement. No manual teardown is required.

Testing

Use AvsbTestProvider in Vitest or Jest to control flag values without a network call:

tsx
1import { AvsbTestProvider, TestData } from '@avsbhq/test'
2import { render, screen } from '@testing-library/react'
3import { CheckoutPage } from './CheckoutPage'
4
5const td = TestData.flag('checkout-v2').booleanFlag().fallthroughVariation(true)
6
7render(
8 <AvsbTestProvider flags={[td.build()]}>
9 <CheckoutPage />
10 </AvsbTestProvider>
11)
12
13expect(screen.getByTestId('new-checkout')).toBeInTheDocument()

What's next