React

Guide

Setup

Add the client to your dependencies:

npm i react-tggl-client

Add the provider to your app:

import { TgglClient, TgglProvider } from 'react-tggl-client'
 
// Instanciate it outside of your component
const client = new TgglClient('YOUR_API_KEY')
 
const App = () => {
  return (
    <TgglProvider client={client}>
      {/*...*/}
    </TgglProvider>
  )
}

For server-side-rendering you can pass the list of active flags directly to the client so the user does not have to re-fetch this list via the API.

const client = new TgglClient('YOUR_API_KEY', { 
  initialActiveFlags: {
    flagA: null,
    flagB: 'foo',
  }, 
})

Read the Node.js client documentation more client specific information.

Updating the context

You can now change the context anywhere in the app using the useTggl hook:

import { useTggl } from 'react-tggl-client'
 
const MyComponent = () => {
  const { user } = useAuth()
  const { updateContext } = useTggl()
 
  useEffect(() => {
    if (user) {
      updateContext({ userId: user.id, email: user.email })
    } else {
      updateContext({ userId: null, email: null })
    }
  }, [user])
 
  return <></>
}

updateContext only updates the keys you specify, it merges the context you pass as argument into the existing context. Alternatively you can use setContext to override the context completely.

Checking flag results

Use the useFlag hook to get the state of a flag:

import { useFlag } from 'react-tggl-client'
 
const MyComponent = () => {
  const { active } = useFlag('myFlag')
  
  //...
}

You may also get the value of a flag:

const MyComponent = () => {
  const { value } = useFlag('myFlag')
  
  //...
}

Typing

Using the Tggl CLI you can run an introspection query to generate the TypeScript types for your flags and context.

npm i --save-dev tggl-cli
tggl typing -k <SERVER_API_KEY> -o src/tggl.d.ts -p react-tggl-client

Replace <SERVER_API_KEY> with your server API key or use the TGGL_API_KEY environment variable and omit the -k option. You should run this command everytime you need to update the typing. Your IDE will now autocomplete and type-check the context properties and all flag names and values.

Autocomplete react 2x

active vs value

By design, you have no way of telling apart an inactive flag, a non-existing flag, a deleted flag, or a network error. This design choice prevents anything from breaking your app by just deleting a flag, messing up the API key rotation, or any other unforeseen event, it will simply consider any flag to be inactive.

Tip

Do not use value if you simply want to know if a flag is active or not, use active instead.

value gives you the value of an active flag, and this value may be "falsy" (null, false, 0, or empty string), leading to unexpected behaviors:

if (value) {
  // If flag is active, but its value is falsy this block won't be executed
}
 
if (active) {
  // Even if flag has a falsy value, this block will be executed
}

Tracking flags evaluation events

Tggl works nicely with your already existing analytics tool. You can track all flag evaluation events in one place and forward it to your analytics to compute conversion rates for A/B testing.

const App = () => {
  return (
    <TgglProvider
      client={client}
      onFlagEvaluation={({ slug, active, value }) => {
        trackEvent('Flag evaluated', { slug, active, value })
      }}
    >
      {/*...*/}
    </TgglProvider>
  )
}

Amplitude

If you are using Amplitude, tracking is automatic, you don't need to do anything. Just make sure the Amplitude SDK is available on window.amplitude. [Tggl] Flag evaluated events will be sent to Amplitude with slug, active, and value.

If you are importing the Amplitude SDK via a <script /> tag, you do not need to do anything. If you are using npm, you need to expose the amplitude object to the window object like so:

import * as amplitude from '@amplitude/analytics-browser';
 
window.amplitude = amplitude

Reference

TgglClient

The client used to query the Tggl API.

const client = new TgglClient('YOUR_API_KEY')

Read more about the Node.js client.

TgglProvider

Place this component at the root of your app. It gives your app access to the client and the state of the client.

<TgglProvider 
  client={client} 
  initialContext={{ foo: 'bar' }}
  onFlagEvaluation={trackFlagEvaluation}
>
  {/*...*/}
</TgglProvider>

client

Pass a TgglClient that will be used to evaluate flags.

initialContext

Allows you to pass an initial value.

Warning

Updating the value of initialContext will have no effect, use the useTggl hook instead

onFlagEvaluation

This function is called everytime a flag is evaluated. It takes an object as only parameter with the following keys: slug, active, ans value.

useTggl

You can use this hook anywhere inside the <TgglProvider />. It is mostly useful for updating the context with setContext and updateContext.

function useTggl(): {
  client: TgglClient
  setContext: (context: Context) => void
  updateContext: (context: Context) => void
}

client

Returns the client instance passed to <TgglProvider />.

setContext

Override the context and triggers an API call to evaluate flags.

updateContext

Just like setContext but keys are merged into the existing context. This should be used if you wish to only update a few keys, leaving the rest unchanged.

useFlag

function useFlag(slug: string): {
  active: boolean
  value: any | undefined
  loading: boolean
  error: any
}
 
function useFlag(
  slug: string,
  defaultValue: any
): {
  active: boolean
  value: any
  loading: boolean
  error: any
}
Tip

Only read the keys that you really need to avoid unnecessary re-renders.

active

True when the flag is active, false otherwise.

value

The value of the flag or undefined if the flag is not active. You can pass a default value as second parameter of this hook to be used when the flag is not active.

Always use active instead of value if you only want to know if a flag is active or not. Otherwise, a falsy value (null, '', 0, false) might lead to unexpected behavior.

loading

True when an API call is being performed.

error

The error thrown by the last API call if any.