diff --git a/guides/self-opt-in.md b/guides/self-opt-in.md index 474a4f3..0499d09 100644 --- a/guides/self-opt-in.md +++ b/guides/self-opt-in.md @@ -7,125 +7,23 @@ icon: browser Use Reflag's React SDK to let users opt themselves—or their company—into beta and experimental features. -For an overview of how opt-in affects access and how memberships are managed in Reflag, see [End-user opt-in](../product-handbook/end-user-opt-in.md). - ## Before you begin -1. [Configure one or more non-secret flags for end-user opt-in](../product-handbook/end-user-opt-in.md#configure-end-user-opt-in). -2. Set **Access** to **Some** in every environment where opting in should be available. -3. Include a `user.id` in the Reflag context for user opt-in. To support company opt-in, also include a `company.id`. - -## Quick start - -Render the available opt-in flags and let the current user set their opt-in status. - -If you're using `` without a `` boundary, see the loading section below. - -```tsx -import { useState } from "react"; -import { - type OptInFlag, - useOptInFlags, - useSetOptIn, -} from "@reflag/react-sdk"; -import { Spinner } from "your-component-library"; - -function OptInPage() { - const { flags: optInFlags } = useOptInFlags(); - - if (optInFlags.length === 0) { - return

No opt-in flags are available.

; - } - - return optInFlags.map((flag) => ( - - )); -} - -function OptInFlagCard({ flag }: { flag: OptInFlag }) { - const setOptIn = useSetOptIn(); - const [isUpdating, setIsUpdating] = useState(false); - const [updateError, setUpdateError] = useState(null); - const label = flag.userOptedIn ? "Cancel opt-in" : `Try ${flag.name}`; - - async function updateOptIn() { - setUpdateError(null); - setIsUpdating(true); - - try { - const response = await setOptIn(flag.key, { - optedIn: !flag.userOptedIn, - }); - - if (response?.ok === false) { - throw new Error("Opt-in request failed"); - } - } catch { - setUpdateError(`Could not update ${flag.name}. Please try again.`); - } finally { - setIsUpdating(false); - } - } - - return ( -
-

{flag.name}

- {flag.description &&

{flag.description}

} - - {updateError &&

{updateError}

} -
- ); -} -``` - -`setOptIn()` returns a promise that resolves after the SDK applies the latest flag state, confirms the membership change, and notifies components using `useOptInFlags()`. React may not have committed the resulting render yet. - -`useOptInFlags()` keeps the list synchronized with Reflag. `useSetOptIn()` changes the current user's opt-in by default and requires the current Reflag context to include a `user.id`. - -## Company opt-in - -To change the current company's opt-in, pass `scope: "company"`. The current Reflag context must include a `company.id`. - -```tsx -setOptIn(flag.key, { - optedIn: !flag.companyOptedIn, - scope: "company", -}); -``` - -User and company opt-ins are independent. Setting `optedIn` to `false` removes only the selected scope, so `isOptedIn` remains `true` while either scope is opted in. - -Cancelling every opt-in does not necessarily disable the flag: an access rule may independently enable it for the current context. - -## Managing loading state with `` and without `` - -Only apps using `ReflagBootstrappedProvider` without Suspense need to handle this loading state. Bootstrapped flag data does not include opt-in metadata, so the SDK fetches it when `useOptInFlags()` is first used. +1. Set up the [React SDK](../sdk/@reflag/react-sdk/README.md) and place your opt-in page inside a Reflag provider. +2. [Configure one or more non-secret flags for end-user opt-in](../product-handbook/end-user-opt-in.md#configure-end-user-opt-in). Add a public description to explain each feature in your UI. +3. Set **Access** to **Some** in every environment where opting in should be available. For an opt-in-only feature, leave the other access rules empty. +4. Include a `user.id` in the Reflag context for user opt-in. To support company opt-in, also include a `company.id`. -Check the hook's `isLoading` value before rendering an empty state: +## Build the opt-in page -```tsx -const { flags: optInFlags, isLoading } = useOptInFlags({ suspense: false }); +Follow the [React SDK opt-in example](../sdk/@reflag/react-sdk/README.md#useoptinflags-and-usesetoptin) to list available flags and let users change their membership. The SDK documentation also covers loading, Suspense, error handling, and retrying failed metadata requests. -if (isLoading) { - return ; -} +## Choose the opt-in scope -if (optInFlags.length === 0) { - return

No opt-in flags are available.

; -} -``` +* **User opt-in** applies to the current user and is the SDK default. Use it for personal beta preferences. +* **Company opt-in** applies to users evaluated in the current company. Use `scope: "company"` for an organization-wide opt-in experience. -With a regular `ReflagProvider`, opt-in metadata arrives as part of the normal flags request, so `useOptInFlags().isLoading` remains `false`. Use `useIsLoading()`, suspense or the provider's `loadingComponent` for the normal initial loading state. +User and company memberships are independent. Cancelling one does not remove the other. Even after cancelling both, an access rule may still enable the flag. ## Next steps diff --git a/product-handbook/end-user-opt-in.md b/product-handbook/end-user-opt-in.md index 1a24f9f..45bd974 100644 --- a/product-handbook/end-user-opt-in.md +++ b/product-handbook/end-user-opt-in.md @@ -111,4 +111,4 @@ If you enable opt-in again, retained memberships become active again as long as Reflag does not impose a particular end-user experience. You can build a Labs page, beta settings page, organization-level experiments page, or any other interface that fits your product. -See [Beta feature opt-in](../guides/self-opt-in.md) for a step-by-step React implementation using Reflag's SDK hooks. +See [Build a beta feature opt-in page](../guides/self-opt-in.md) for setup guidance and a link to the React SDK example.