Skip to content

React Native SDK (JSI)

The React Native SDK uses C FFI to call the Rust evaluation core directly from JavaScript via React Native's JavaScript Interface (JSI). This avoids the async bridge overhead and delivers synchronous, near-native evaluation performance.

Installation

bash
npm install @sidekick-flags/react-native
# or
yarn add @sidekick-flags/react-native

iOS

bash
cd ios && pod install

Android

The native library is linked automatically via CMake. No additional steps required.

Quick Start

typescript
import { SidekickNativeClient } from '@sidekick-flags/react-native'

const client = new SidekickNativeClient({
  serverUrl: 'https://flags.yourcompany.com',
  sdkKey: 'your-sdk-key',
})

// Connect on app start (typically in App.tsx)
useEffect(() => {
  client.connect()
  return () => client.disconnect()
}, [])

// Evaluate flags synchronously anywhere
const enabled = client.isEnabled('new-onboarding', userId, {
  plan: user.plan,
  country: user.country,
})

API Reference

new SidekickNativeClient(options)

OptionTypeRequiredDescription
serverUrlstringYesBase URL of your Sidekick server
sdkKeystringNoSDK key for authentication
reconnectDelayMsnumberNoSSE reconnect delay in ms (default: 5000)

client.connect(): void

Initiates the SSE connection in the background. Flags are loaded as they arrive; isEnabled() returns false for unknown flags during bootstrap.

Unlike the web SDK, connect() does not return a Promise — it fires and forgets, consistent with React Native's event-driven model.

client.isEnabled(flagKey, userKey, attributes): boolean

Synchronous flag evaluation via JSI. Runs on the JS thread, calls into the Rust library without bridging overhead.

client.disconnect(): void

Tears down the SSE connection. Call in your cleanup effect.

Usage with React Navigation

typescript
// App.tsx
import { NavigationContainer } from '@react-navigation/native'
import { SidekickNativeClient } from '@sidekick-flags/react-native'
import { createContext, useContext, useEffect, useState } from 'react'

const FlagContext = createContext<SidekickNativeClient | null>(null)

export function useFlags() {
  return useContext(FlagContext)!
}

const flagClient = new SidekickNativeClient({
  serverUrl: process.env.EXPO_PUBLIC_SIDEKICK_URL!,
  sdkKey: process.env.EXPO_PUBLIC_SIDEKICK_KEY,
})

export default function App() {
  useEffect(() => {
    flagClient.connect()
    return () => flagClient.disconnect()
  }, [])

  return (
    <FlagContext.Provider value={flagClient}>
      <NavigationContainer>
        {/* ... */}
      </NavigationContainer>
    </FlagContext.Provider>
  )
}
typescript
// screens/HomeScreen.tsx
import { useFlags } from '../App'
import { useUser } from '../hooks/useUser'

export function HomeScreen() {
  const flags = useFlags()
  const user = useUser()

  const showNewUI = flags.isEnabled('new-home-ui', user.id, {
    plan: user.plan,
    beta: user.isBeta ? 'true' : 'false',
  })

  return showNewUI ? <NewHomeUI /> : <LegacyHomeUI />
}

Expo Compatibility

The SDK is compatible with Expo managed workflow via the Expo Dev Client. It is not compatible with Expo Go (which doesn't support native modules).

bash
npx expo install @sidekick-flags/react-native
npx expo prebuild

Platform Support

PlatformArchitectureStatus
iOSarm64Supported
iOS Simulatorx86_64 / arm64Supported
Androidarm64-v8aSupported
Androidarmeabi-v7aSupported
Androidx86_64Supported

Released under the MIT License.