Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/react-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,27 @@ function FeatureOptIn() {

Note: To change the `user.id` or `company.id`, you need to update the props passed to `BucketProvider` instead of using these hooks.

### `useClient()`

Returns the `BucketClient` used by the `BucketProvider`. The client offers more functionality that
is not directly accessible thorough the other hooks.

```tsx
import { useClient } from "@bucketco/react-sdk";

function LoggingWrapper({ children }: { children: ReactNode }) {
const client = useClient();

useEffect(() => {
client.on("enabledCheck", (evt) => {
console.log(`The feature ${evt.key} is ${evt.value} for user.`);
});
}, [client]);

return children;
}
```

## Content Security Policy (CSP)

See [CSP](https://github.com/bucketco/bucket-javascript-sdk/blob/main/packages/browser-sdk/README.md#content-security-policy-csp) for info on using Bucket React SDK with CSP
Expand Down
2 changes: 1 addition & 1 deletion packages/react-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bucketco/react-sdk",
"version": "3.0.0-alpha.6",
"version": "3.0.0-alpha.7",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
41 changes: 24 additions & 17 deletions packages/react-sdk/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ type EmptyConfig = {
payload: undefined;
};

type Feature<TKey extends FeatureKey> = {
export type Feature<TKey extends FeatureKey> = {
isEnabled: boolean;
isLoading: boolean;
config: MaterializedFeatures[TKey] extends boolean
Expand Down Expand Up @@ -195,12 +195,10 @@ type Feature<TKey extends FeatureKey> = {
export function useFeature<TKey extends FeatureKey>(
key: TKey,
): Feature<typeof key> {
const client = useClient();
const {
features: { isLoading },
client,
provider,
} = useContext<ProviderContextType>(ProviderContext);
ensureProvider(provider);

const track = () => client?.track(key);
const requestFeedback = (opts: RequestFeedbackOptions) =>
Expand Down Expand Up @@ -241,8 +239,7 @@ export function useFeature<TKey extends FeatureKey>(
* ```
*/
export function useTrack() {
const { client, provider } = useContext<ProviderContextType>(ProviderContext);
ensureProvider(provider);
const client = useClient();
return (eventName: string, attributes?: Record<string, any> | null) =>
client?.track(eventName, attributes);
}
Expand All @@ -262,8 +259,7 @@ export function useTrack() {
* ```
*/
export function useRequestFeedback() {
const { client, provider } = useContext<ProviderContextType>(ProviderContext);
ensureProvider(provider);
const client = useClient();
return (options: RequestFeedbackData) => client?.requestFeedback(options);
}

Expand All @@ -284,8 +280,7 @@ export function useRequestFeedback() {
* ```
*/
export function useSendFeedback() {
const { client, provider } = useContext<ProviderContextType>(ProviderContext);
ensureProvider(provider);
const client = useClient();
return (opts: UnassignedFeedback) => client?.feedback(opts);
}

Expand All @@ -303,8 +298,7 @@ export function useSendFeedback() {
* ```
*/
export function useUpdateUser() {
const { client, provider } = useContext<ProviderContextType>(ProviderContext);
ensureProvider(provider);
const client = useClient();
return (opts: { [key: string]: string | number | undefined }) =>
client?.updateUser(opts);
}
Expand All @@ -323,8 +317,7 @@ export function useUpdateUser() {
* ```
*/
export function useUpdateCompany() {
const { client, provider } = useContext<ProviderContextType>(ProviderContext);
ensureProvider(provider);
const client = useClient();

return (opts: { [key: string]: string | number | undefined }) =>
client?.updateCompany(opts);
Expand All @@ -345,16 +338,30 @@ export function useUpdateCompany() {
* ```
*/
export function useUpdateOtherContext() {
const { client, provider } = useContext<ProviderContextType>(ProviderContext);
ensureProvider(provider);
const client = useClient();
return (opts: { [key: string]: string | number | undefined }) =>
client?.updateOtherContext(opts);
}

function ensureProvider(provider: boolean) {
/**
* Returns the current `BucketClient` used by the `BucketProvider`.
*
* This is useful if you need to access the `BucketClient` outside of the `BucketProvider`.
*
* ```ts
* const client = useClient();
* client.on("configCheck", () => {
* console.log("configCheck hook called");
* });
* ```
*/
export function useClient() {
const { client, provider } = useContext<ProviderContextType>(ProviderContext);
if (!provider) {
throw new Error(
"BucketProvider is missing. Please ensure your component is wrapped with a BucketProvider.",
);
}

return client;
}
18 changes: 17 additions & 1 deletion packages/react-sdk/test/usage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { version } from "../package.json";
import {
BucketProps,
BucketProvider,
useClient,
useFeature,
useRequestFeedback,
useSendFeedback,
Expand Down Expand Up @@ -138,6 +139,7 @@ beforeAll(() =>
},
}),
);

afterEach(() => server.resetHandlers());
afterAll(() => server.close());

Expand Down Expand Up @@ -311,7 +313,7 @@ describe("useSendFeedback", () => {

await waitFor(async () => {
await result.current({
featureId: "123",
featureKey: "huddles",
score: 5,
});
expect(events).toStrictEqual(["FEEDBACK"]);
Expand Down Expand Up @@ -432,3 +434,17 @@ describe("useUpdateOtherContext", () => {
unmount();
});
});

describe("useClient", () => {
test("gets the client", async () => {
const { result: clientFn, unmount } = renderHook(() => useClient(), {
wrapper: ({ children }) => getProvider({ children }),
});

await waitFor(async () => {
expect(clientFn.current).toBeDefined();
});

unmount();
});
});
Loading