@@ -15,7 +15,56 @@ Feature flags allow you to control feature rollouts and conduct A/B testing with
1515
1616## Quick Start
1717
18- <Tabs items = { [' React/Next.js' , ' Setup' ]} >
18+ <Tabs items = { [' React/Next.js with Auth' , ' React/Next.js Basic' , ' Setup' ]} >
19+
20+ <Tab >
21+ <CodeBlock language = " tsx" filename = " app.tsx" >
22+ { ` 'use client';
23+
24+ import { FlagsProvider, useFlags } from '@databuddy/sdk/react';
25+ import { useSession } from '@databuddy/auth/client';
26+
27+ function App() {
28+ const { data: session, isPending } = useSession();
29+
30+ return (
31+ <FlagsProvider
32+ clientId="your-website-id"
33+ apiUrl="https://api.databuddy.cc"
34+ isPending={isPending}
35+ user={session?.user ? {
36+ userId: session.user.id,
37+ email: session.user.email,
38+ properties: {
39+ plan: session.user.plan || 'free',
40+ role: session.user.role || 'user',
41+ organization: session.user.organizationId,
42+ region: 'us-east', // or from user location
43+ }
44+ } : undefined}
45+ >
46+ <MyComponent />
47+ </FlagsProvider>
48+ );
49+ }
50+
51+ function MyComponent() {
52+ const { isEnabled, getValue } = useFlags();
53+
54+ const showNewFeature = isEnabled('new-dashboard');
55+ const showBetaFeatures = isEnabled('beta-features');
56+ const darkModeEnabled = getValue('dark-mode-default', false);
57+
58+ return (
59+ <div className={darkModeEnabled ? 'dark' : ''}>
60+ {showNewFeature && <NewDashboard />}
61+ {showBetaFeatures && <BetaFeatures />}
62+ <button>Click me</button>
63+ </div>
64+ );
65+ } ` }
66+ </CodeBlock >
67+ </Tab >
1968
2069<Tab >
2170<CodeBlock language = " tsx" filename = " app.tsx" >
@@ -40,9 +89,9 @@ function App() {
4089
4190function MyComponent() {
4291 const { isEnabled } = useFlags();
43-
92+
4493 const showNewFeature = isEnabled('new-feature');
45-
94+
4695 return (
4796 <div>
4897 {showNewFeature && <NewFeature />}
@@ -87,9 +136,22 @@ const showNewUI = isEnabled('new-ui-rollout');`}
87136 apiUrl="https://api.databuddy.cc"
88137 user={{
89138 userId: currentUser.id,
90- email: currentUser.email
139+ email: currentUser.email,
140+ properties: {
141+ plan: currentUser.plan || 'free',
142+ role: currentUser.role || 'user',
143+ organization: currentUser.organizationId,
144+ region: currentUser.region || 'us-east',
145+ signupDate: currentUser.createdAt,
146+ featureUsage: {
147+ reportsViewed: currentUser.reportsViewed || 0,
148+ dashboardsCreated: currentUser.dashboardsCreated || 0,
149+ }
150+ }
91151 }}
152+ isPending={isLoadingSession} // from useSession hook
92153 debug={process.env.NODE_ENV === 'development'}
154+ autoFetch={true} // default: true
93155>
94156 <App />
95157</FlagsProvider> ` }
@@ -98,22 +160,60 @@ const showNewUI = isEnabled('new-ui-rollout');`}
98160## Hook API
99161
100162<CodeBlock language = " tsx" >
101- { ` const { isEnabled, fetchAllFlags, refresh } = useFlags();
163+ { ` const {
164+ isEnabled,
165+ getValue,
166+ fetchAllFlags,
167+ updateUser,
168+ refresh
169+ } = useFlags();
102170
103171// Check if flag is enabled
104172const showFeature = isEnabled('my-feature');
173+ const darkModeDefault = getValue('dark-mode', false);
105174
106175// Refresh all flags
107176await fetchAllFlags(); ` }
108177</CodeBlock >
109178
179+ ## Why isPending Matters
180+
181+ The ` isPending ` prop is crucial for preventing race conditions and ensuring consistent user experiences:
182+
183+ - ** Prevents Flash of Incorrect Content** : Without ` isPending ` , flags might evaluate with stale user data during authentication state changes
184+ - ** Avoids Unnecessary API Calls** : The SDK waits for authentication to complete before making flag requests
185+ - ** Consistent User Experience** : Users won't see feature toggles based on anonymous user data when they're actually logged in
186+ - ** Better Performance** : Reduces redundant flag evaluations during session transitions
187+
188+ <CodeBlock language = " tsx" >
189+ { ` // ❌ Bad: No isPending - flags evaluate with wrong user context
190+ <FlagsProvider user={undefined}>
191+ <App /> // Shows anonymous features briefly, then switches
192+ </FlagsProvider>
193+
194+ // ✅ Good: Waits for session before evaluating flags
195+ <FlagsProvider isPending={isPending} user={session?.user ? {...} : undefined}>
196+ <App /> // Shows correct features immediately
197+ </FlagsProvider> ` }
198+ </CodeBlock >
199+
110200## User Targeting
111201
112202Target specific users or groups from your dashboard:
113203
114- - ** User ID** : Target specific users
115- - ** Email** : Target by email or domain
116- - ** Properties** : Target by custom user properties
204+ - ** User ID** : Target specific users by their unique identifier
205+ - ** Email** : Target by email address or domain (e.g., ` @company.com ` )
206+ - ** Custom Properties** : Target by user attributes like plan tier, role, organization, region, signup date, or feature usage patterns
207+
208+ ### Advanced Targeting with Custom Properties
209+
210+ Custom properties enable sophisticated targeting strategies:
211+
212+ - ** Plan-based Rollouts** : ` plan: 'premium' ` → Show premium features only to paying users
213+ - ** Geographic Targeting** : ` region: 'us-east' ` → Test features in specific regions
214+ - ** Behavioral Targeting** : ` featureUsage.reportsViewed > 10 ` → Target power users
215+ - ** A/B Testing** : ` experimentGroup: 'A' ` → Segment users for experiments
216+ - ** Time-based** : ` signupDate > '2024-01-01' ` → Target new vs. existing users
117217
118218<CodeBlock language = " tsx" >
119219{ ` <FlagsProvider
@@ -139,6 +239,39 @@ Target specific users or groups from your dashboard:
139239
140240Enable debug mode to see flag evaluation in the browser console.
141241
242+ ## Performance Benefits
243+
244+ - ** Client-side Caching** : Flags are cached in IndexedDB and localStorage for instant loading
245+ - ** Intelligent Updates** : Only re-evaluates flags when user context changes
246+ - ** Background Sync** : Fetches flag updates without blocking the UI
247+ - ** Minimal Bundle Size** : Lightweight SDK with zero external dependencies
248+
249+ ## Best Practices
250+
251+ 1 . ** Use ` isPending ` ** with authentication to prevent race conditions
252+ 2 . ** Pass Custom Properties** for granular targeting and A/B testing
253+ 3 . ** Enable Debug Mode** during development to monitor flag evaluation
254+ 4 . ** Handle Flag Changes** gracefully with loading states
255+ 5 . ** Update User Context** after profile changes to refresh flag evaluation
256+
257+ <CodeBlock language = " tsx" >
258+ { ` // Best practice: Handle loading states
259+ function FeatureComponent() {
260+ const { isEnabled } = useFlags();
261+ const [isLoading, setIsLoading] = useState(true);
262+
263+ useEffect(() => {
264+ // Simulate loading or wait for flags
265+ const timer = setTimeout(() => setIsLoading(false), 100);
266+ return () => clearTimeout(timer);
267+ }, []);
268+
269+ if (isLoading) return <Skeleton />;
270+
271+ return isEnabled('new-feature') ? <NewFeature /> : <OldFeature />;
272+ } ` }
273+ </CodeBlock >
274+
142275---
143276
144277Ready to get started? [ Create your first feature flag in the dashboard →] ( https://app.databuddy.cc/login )
0 commit comments