Feature Flags
Expose features to your users using feature flags.
Feature flags allow you to toggle functionality on/off during runtime and give people access to certain features based on their attributes, like their role or the current billing plan.
- Beta
Buy Pro
- 0.38.0 (latest)
Import
FeaturesProvider
: The context provider that manages state.Has
: Conditionally render components.useFlag
: Hook that returns a flag value.useFeatures
: Returns the features context.useHasFeature
: Hook used to check if user has one or more features.
import { FeaturesProvider, Has, useFlag } from '@saas-ui-pro/feature-flags'
Setup
Add FeaturesProvider
in the root of you application, to make sure the features context is available throughout your app.
The options can either be hardcoded or preferably loaded from your database, so it can be updated on the fly.
The provider options contain segments
with attributes (attr
) that can be matched against the identify user, more on this below.
A user can match multiple segments, and segments can have multiple features
. A feature can be either a string
or Feature
object with a id
and value
.
Strings will be parsed as booleans, while feature objects support custom values.
Configuration
Here is an example config.
import { FeaturesProvider, FeaturesOptions } from '@saas-ui-pro/feature-flags'const options: FeaturesOptions = {segments: [{id: 'admin',attr: [{key: 'role',value: 'admin',},],features: ['settings', { id: 'value-feature', value: 'enabled' }],},{id: 'proPlan',attr: [{key: 'plan',value: 'pro',},],features: ['inbox'],},],}export default function App({ children }) {return <FeaturesProvider value={options}>{chilren}</FeaturesProvider>}
Identify a user
Identifying a user will match their attributes against the configured segments.
Use the useFeatures
hook to get access to the features context and create a hook to identify the user.
The user object is typically accessible through your AuthProvider
using the useAuth
hook.
If you need additional attributes you can add those as well.
Then add a useEffect
hook to call identify
like to example below.
import { useFeatures } from '@saas-ui-pro/feature-flags'import { useAuth } from '@saas-ui/auth'export default function Layout({ children }) {const features = useFeatures()const { user } = useAuth()// const user = {// id: 1,// plan: 'pro',// role: 'admin'// }React.useEffect(() => {if (features.isReady && user) {features.identify(user)}}, [features.isReady, user])return <>{children}</>}
Usage
Basic example
import { Button, Stack, Text } from '@chakra-ui/react'import { useFeatures } from '@saas-ui-pro/feature-flags'export default function App() {const features = useFeatures()const [plan, setPlan] = React.useState('basic')const user = React.useMemo(() => {return {id: 1,role: 'admin',plan,}}, [plan])const upgrade = () => {setPlan('pro')}const downgrade = () => {setPlan('basic')}React.useEffect(() => {if (features.isReady) {features.identify(user)}}, [features.isReady, user])return (<Stack>{plan === 'pro' ? (<Button onClick={downgrade}>Downgrade</Button>) : (<Button onClick={upgrade}>Upgrade</Button>)}<Text>Features: {Object.keys(features.flags).join(', ')}</Text></Stack>)}
Has
import { Button } from '@chakra-ui/react'import { Has } from '@saas-ui-pro/feature-flags'export default function App() {return (<Has feature="settings"><Button colorScheme="green">Settings Enabled</Button></Has>)}
Has with fallback
import { Button } from '@chakra-ui/react'import { Has } from '@saas-ui-pro/feature-flags'export default function App() {return (<Hasfeature="beta-feature"fallback={<Button colorScheme="red">Enable beta features</Button>}><Button colorScheme="green">Disable beta features</Button></Has>)}
Has with multiple features
import { Button } from '@chakra-ui/react'import { Has } from '@saas-ui-pro/feature-flags'export default function App() {return (<Hasfeature={['settings', 'enterprise-feature']}fallback={<Button colorScheme="red">Feature Disabled</Button>}><Button colorScheme="green">Feature Enabled</Button></Has>)}
Has with exact features
import { Button } from '@chakra-ui/react'import { Has } from '@saas-ui-pro/feature-flags'export default function App() {return (<Hasfeature={['settings', 'beta']}exact={false}fallback={<Button colorScheme="red">Feature Disabled</Button>}><Button colorScheme="green">Feature Enabled</Button></Has>)}
Has with value
import { Button } from '@chakra-ui/react'import { Has } from '@saas-ui-pro/feature-flags'export default function App() {return (<Has feature="value-feature" value="enabled"><Button colorScheme="green">Feature Enabled</Button></Has>)}
Has with multiple values
import { Button } from '@chakra-ui/react'import { Has } from '@saas-ui-pro/feature-flags'export default function App() {return (<Hasfeature={['settings', 'value-feature']}value="enabled"fallback={<Button colorScheme="red">Feature Disabled</Button>}><Button colorScheme="green">Feature Enabled</Button></Has>)}
Has with render prop
import { Button } from '@chakra-ui/react'import { Has } from '@saas-ui-pro/feature-flags'export default function App() {return (<Has feature={['settings']}>{({ flags }) => {const features = Object.keys(flags)return (<Button colorScheme="green">Feature Enabled: {features[0]}</Button>)}}</Has>)}
useFlag
import { Card, Button } from '@chakra-ui/react'import { PropertyList, Property } from '@saas-ui/react'import { useFlag } from '@saas-ui-pro/feature-flags'export default function Settings() {return (<Card px="4"><PropertyList><Property label="settings" value={String(useFlag('settings'))} /><Property label="beta" value={String(useFlag('beta'))} /><Property label="inbox" value={String(useFlag('inbox'))} /><Propertylabel="value-feature"value={String(useFlag('value-feature'))}/></PropertyList></Card>)}
useHasFeature
import { Box } from '@chakra-ui/react'import { EmptyState } from '@saas-ui/react'import { useHasFeature } from '@saas-ui-pro/feature-flags'export default function Settings() {const enabled = useHasFeature('settings')if (!enabled) {return <EmptyState title="No access" />}return <Box>Settings</Box>}
Multiple features
import { Box } from '@chakra-ui/react'import { EmptyState } from '@saas-ui/react'import { useHasFeature } from '@saas-ui-pro/feature-flags'export default function Settings() {const enabled = useHasFeature(['settings', 'beta'])if (!enabled) {return <EmptyState title="No access" />}return <Box>Settings</Box>}
Was this helpful?