44[ ![ License] ( https://img.shields.io/github/license/replane-dev/replane-javascript )] ( https://github.com/replane-dev/replane-javascript/blob/main/LICENSE )
55[ ![ Community] ( https://img.shields.io/badge/discussions-join-blue?logo=github )] ( https://github.com/orgs/replane-dev/discussions )
66
7- React SDK for [ Replane] ( https://github.com/replane-dev/replane-javascript ) - feature flags and remote configuration.
7+ React SDK for [ Replane] ( https://github.com/replane-dev/replane ) - feature flags and remote configuration.
88
99## Installation
1010
@@ -24,14 +24,14 @@ yarn add @replanejs/react
2424## Quick Start
2525
2626``` tsx
27- import { ReplaneProvider , useConfig } from ' @replanejs/react' ;
27+ import { ReplaneProvider , useConfig } from " @replanejs/react" ;
2828
2929function App() {
3030 return (
3131 <ReplaneProvider
3232 options = { {
33- baseUrl: ' https://your-replane-server.com' ,
34- sdkKey: ' your-sdk-key' ,
33+ baseUrl: " https://your-replane-server.com" ,
34+ sdkKey: " your-sdk-key" ,
3535 }}
3636 loader = { <div >Loading...</div >}
3737 >
@@ -41,13 +41,9 @@ function App() {
4141}
4242
4343function MyComponent() {
44- const isFeatureEnabled = useConfig <boolean >(' feature-flag-name' );
44+ const isFeatureEnabled = useConfig <boolean >(" feature-flag-name" );
4545
46- return (
47- <div >
48- { isFeatureEnabled ? ' Feature is enabled!' : ' Feature is disabled' }
49- </div >
50- );
46+ return <div >{ isFeatureEnabled ? " Feature is enabled!" : " Feature is disabled" } </div >;
5147}
5248```
5349
@@ -62,36 +58,36 @@ Provider component that makes the Replane client available to your component tre
6258The provider creates and manages the client internally. Use an Error Boundary to handle initialization errors:
6359
6460``` tsx
65- import { ErrorBoundary } from ' react-error-boundary' ;
61+ import { ErrorBoundary } from " react-error-boundary" ;
6662
6763<ErrorBoundary fallback = { <div >Failed to load configuration</div >} >
6864 <ReplaneProvider
6965 options = { {
70- baseUrl: ' https://your-replane-server.com' ,
71- sdkKey: ' your-sdk-key' ,
66+ baseUrl: " https://your-replane-server.com" ,
67+ sdkKey: " your-sdk-key" ,
7268 }}
7369 loader = { <LoadingSpinner />}
7470 >
7571 <App />
7672 </ReplaneProvider >
77- </ErrorBoundary >
73+ </ErrorBoundary >;
7874```
7975
8076#### 2. With pre-created client
8177
8278Use this when you need more control over client lifecycle:
8379
8480``` tsx
85- import { createReplaneClient } from ' @replanejs/sdk' ;
81+ import { createReplaneClient } from " @replanejs/sdk" ;
8682
8783const client = await createReplaneClient ({
88- baseUrl: ' https://your-replane-server.com' ,
89- sdkKey: ' your-sdk-key' ,
84+ baseUrl: " https://your-replane-server.com" ,
85+ sdkKey: " your-sdk-key" ,
9086});
9187
9288<ReplaneProvider client = { client } >
9389 <App />
94- </ReplaneProvider >
90+ </ReplaneProvider >;
9591```
9692
9793#### 3. With Suspense
@@ -103,8 +99,8 @@ Integrates with React Suspense for loading states:
10399 <Suspense fallback = { <LoadingSpinner />} >
104100 <ReplaneProvider
105101 options = { {
106- baseUrl: ' https://your-replane-server.com' ,
107- sdkKey: ' your-sdk-key' ,
102+ baseUrl: " https://your-replane-server.com" ,
103+ sdkKey: " your-sdk-key" ,
108104 }}
109105 suspense
110106 >
@@ -120,7 +116,7 @@ Restore a client from a snapshot obtained on the server. This is synchronous and
120116
121117``` tsx
122118// On the server
123- const serverClient = await createReplaneClient ({ baseUrl: ' ...' , sdkKey: ' ...' });
119+ const serverClient = await createReplaneClient ({ baseUrl: " ..." , sdkKey: " ..." });
124120const snapshot = serverClient .getSnapshot ();
125121// Pass snapshot to client via props, context, or serialized HTML
126122
@@ -130,13 +126,13 @@ const snapshot = serverClient.getSnapshot();
130126 snapshot ,
131127 // Optional: connect for live updates
132128 connection: {
133- baseUrl: ' https://your-replane-server.com' ,
134- sdkKey: ' your-sdk-key' ,
129+ baseUrl: " https://your-replane-server.com" ,
130+ sdkKey: " your-sdk-key" ,
135131 },
136132 }}
137133>
138134 <App />
139- </ReplaneProvider >
135+ </ReplaneProvider >;
140136```
141137
142138The restored client is immediately available with no loading state. If ` connection ` is provided, it will establish a connection for real-time updates in the background.
@@ -148,17 +144,21 @@ Hook to retrieve a configuration value. Automatically subscribes to updates and
148144``` tsx
149145function MyComponent() {
150146 // Basic usage
151- const theme = useConfig <string >(' theme' );
147+ const theme = useConfig <string >(" theme" );
152148
153149 // With evaluation context
154- const discount = useConfig <number >(' discount-percentage' , {
150+ const discount = useConfig <number >(" discount-percentage" , {
155151 context: {
156- userId: ' 123' ,
152+ userId: " 123" ,
157153 isPremium: true ,
158154 },
159155 });
160156
161- return <div >Theme: { theme } , Discount: { discount } %</div >;
157+ return (
158+ <div >
159+ Theme: { theme } , Discount: { discount } %
160+ </div >
161+ );
162162}
163163```
164164
@@ -172,7 +172,7 @@ function MyComponent() {
172172
173173 const handleClick = () => {
174174 // Access replane methods directly
175- const value = replane .get (' some-config' );
175+ const value = replane .get (" some-config" );
176176 console .log (value );
177177 };
178178
@@ -185,7 +185,7 @@ function MyComponent() {
185185Factory function to create a typed version of ` useReplane ` . Returns a hook that provides the typed client directly:
186186
187187``` tsx
188- import { createReplaneHook } from ' @replanejs/react' ;
188+ import { createReplaneHook } from " @replanejs/react" ;
189189
190190// Define your config types
191191interface AppConfigs {
@@ -201,10 +201,10 @@ function MyComponent() {
201201 const replane = useAppReplane ();
202202
203203 // replane.get is now typed - autocomplete works!
204- const theme = replane .get (' theme' );
204+ const theme = replane .get (" theme" );
205205 // ^? { darkMode: boolean; primaryColor: string }
206206
207- return <div >Dark mode: { theme .darkMode ? ' on ' : ' off' } </div >;
207+ return <div >Dark mode: { theme .darkMode ? " on " : " off" } </div >;
208208}
209209```
210210
@@ -213,7 +213,7 @@ function MyComponent() {
213213Factory function to create a typed version of ` useConfig ` . This provides autocomplete for config names and type inference for values:
214214
215215``` tsx
216- import { createConfigHook } from ' @replanejs/react' ;
216+ import { createConfigHook } from " @replanejs/react" ;
217217
218218// Define your config types
219219interface AppConfigs {
@@ -227,24 +227,24 @@ const useAppConfig = createConfigHook<AppConfigs>();
227227
228228function MyComponent() {
229229 // Autocomplete for config names, automatic type inference
230- const theme = useAppConfig (' theme' );
230+ const theme = useAppConfig (" theme" );
231231 // ^? { darkMode: boolean; primaryColor: string }
232232
233- const features = useAppConfig (' features' );
233+ const features = useAppConfig (" features" );
234234 // ^? { beta: boolean; analytics: boolean }
235235
236- const maxItems = useAppConfig (' maxItems' );
236+ const maxItems = useAppConfig (" maxItems" );
237237 // ^? number
238238
239239 // With context override
240- const premiumFeatures = useAppConfig (' features' , {
241- context: { userId: ' 123' , plan: ' premium' },
240+ const premiumFeatures = useAppConfig (" features" , {
241+ context: { userId: " 123" , plan: " premium" },
242242 });
243243
244244 return (
245245 <div >
246- <p >Dark mode: { theme .darkMode ? ' on ' : ' off' } </p >
247- <p >Beta enabled: { features .beta ? ' yes' : ' no ' } </p >
246+ <p >Dark mode: { theme .darkMode ? " on " : " off" } </p >
247+ <p >Beta enabled: { features .beta ? " yes" : " no " } </p >
248248 <p >Max items: { maxItems } </p >
249249 </div >
250250 );
@@ -256,12 +256,12 @@ function MyComponent() {
256256Utility function to clear the suspense cache. Useful for testing or forcing re-initialization:
257257
258258``` tsx
259- import { clearSuspenseCache } from ' @replanejs/react' ;
259+ import { clearSuspenseCache } from " @replanejs/react" ;
260260
261261// Clear cache for specific options
262262clearSuspenseCache ({
263- baseUrl: ' https://your-replane-server.com' ,
264- sdkKey: ' your-sdk-key' ,
263+ baseUrl: " https://your-replane-server.com" ,
264+ sdkKey: " your-sdk-key" ,
265265});
266266
267267// Clear entire cache
@@ -275,16 +275,16 @@ The SDK is fully typed. For the best TypeScript experience, use the hook factory
275275``` tsx
276276// Define all your config types in one interface
277277interface AppConfigs {
278- ' theme-config' : {
278+ " theme-config" : {
279279 darkMode: boolean ;
280280 primaryColor: string ;
281281 };
282- ' feature-flags' : {
282+ " feature-flags" : {
283283 newUI: boolean ;
284284 beta: boolean ;
285285 };
286- ' max-items' : number ;
287- ' welcome-message' : string ;
286+ " max-items" : number ;
287+ " welcome-message" : string ;
288288}
289289
290290// Create typed hooks once
@@ -293,7 +293,7 @@ const useAppConfig = createConfigHook<AppConfigs>();
293293
294294// Use throughout your app with full type safety
295295function Settings() {
296- const theme = useAppConfig (' theme-config' );
296+ const theme = useAppConfig (" theme-config" );
297297 // ^? { darkMode: boolean; primaryColor: string }
298298
299299 const replane = useAppReplane ();
@@ -302,7 +302,7 @@ function Settings() {
302302
303303 return (
304304 <div style = { { color: theme .primaryColor }} >
305- Dark mode: { theme .darkMode ? ' enabled' : ' disabled' }
305+ Dark mode: { theme .darkMode ? " enabled" : " disabled" }
306306 </div >
307307 );
308308}
@@ -313,7 +313,7 @@ function Settings() {
313313The provider throws errors during rendering so they can be caught by React Error Boundaries:
314314
315315``` tsx
316- import { Component , ReactNode } from ' react' ;
316+ import { Component , ReactNode } from " react" ;
317317
318318class ErrorBoundary extends Component <
319319 { children: ReactNode ; fallback: ReactNode },
@@ -338,13 +338,13 @@ class ErrorBoundary extends Component<
338338 <ReplaneProvider options = { options } loader = { <Loading />} >
339339 <App />
340340 </ReplaneProvider >
341- </ErrorBoundary >
341+ </ErrorBoundary >;
342342```
343343
344344Or use a library like ` react-error-boundary ` :
345345
346346``` tsx
347- import { ErrorBoundary } from ' react-error-boundary' ;
347+ import { ErrorBoundary } from " react-error-boundary" ;
348348
349349<ErrorBoundary
350350 fallbackRender = { ({ error , resetErrorBoundary }) => (
@@ -358,7 +358,7 @@ import { ErrorBoundary } from 'react-error-boundary';
358358 <ReplaneProvider options = { options } loader = { <Loading />} >
359359 <App />
360360 </ReplaneProvider >
361- </ErrorBoundary >
361+ </ErrorBoundary >;
362362```
363363
364364## Community
0 commit comments