> ## Documentation Index
> Fetch the complete documentation index at: https://gleanfeed.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Use the widget with React

> Install the React provider, open widget views from your components, and pass server-signed customer identity safely.

`@gleanfeed/react` wraps the browser widget with a provider and hook. Use it in React 18 or 19 apps, including Next.js App Router projects.

## Install the packages

Install both the React wrapper and its widget dependency:

```bash theme={null}
npm install @gleanfeed/react @gleanfeed/widget
```

## Add the provider

Create a client component near the root of your app. The package can be imported during server rendering, but the provider initializes the widget after the browser mounts it.

```tsx theme={null}
"use client";

import { GleanFeedProvider, type GleanFeedUser } from "@gleanfeed/react";
import type { ReactNode } from "react";

export function FeedbackProvider({
  children,
  user,
}: {
  children: ReactNode;
  user?: GleanFeedUser;
}) {
  return (
    <GleanFeedProvider
      workspace="acme"
      workspaceId="YOUR_WORKSPACE_ID"
      user={user}
      defaultView="feedback"
    >
      {children}
    </GleanFeedProvider>
  );
}
```

The provider accepts the same configuration as [`init()`](/widget/configuration#configuration-options). Unmounting it removes the launcher, iframe, event listeners, and notification polling. React Strict Mode remounts do not leave duplicate widget instances.

## Open and close the widget

Call the hook from a client component below the provider:

```tsx theme={null}
"use client";

import { useGleanFeed } from "@gleanfeed/react";

export function FeedbackControls() {
  const { openFeedback, openRoadmap, openChangelog, close } = useGleanFeed();

  return (
    <nav aria-label="Product feedback">
      <button type="button" onClick={openFeedback}>
        Send feedback
      </button>
      <button type="button" onClick={openRoadmap}>
        Roadmap
      </button>
      <button type="button" onClick={openChangelog}>
        Updates
      </button>
      <button type="button" onClick={close}>
        Close
      </button>
    </nav>
  );
}
```

You can also call `open("feedback" | "roadmap" | "changelog")` when a single component needs to choose the view dynamically.

## Pass signed customer identity

<Warning>
  Generate the signature on your server. Never import the widget secret into a client component or
  expose it through a `NEXT_PUBLIC_...` environment variable.
</Warning>

Follow the [identity signing contract](/widget/identity), then pass only the signed `GleanFeedUser` object from your server component to `FeedbackProvider`. If the signed-in customer changes without remounting the provider, reidentify them from a client component:

```tsx theme={null}
"use client";

import { useEffect } from "react";
import { useGleanFeed, type GleanFeedUser } from "@gleanfeed/react";

export function CustomerIdentity({ user }: { user: GleanFeedUser }) {
  const { identify } = useGleanFeed();

  useEffect(() => {
    void identify(user);
  }, [identify, user]);

  return null;
}
```

Prefer passing `user` to `GleanFeedProvider`; use `identify()` when your app changes customers while the provider stays mounted.

## Compatibility

The wrapper supports React 18.2 and React 19 and depends on a compatible
`@gleanfeed/widget`. During `0.x`, pin exact versions when upgrades require a
controlled test window. Review the full [version and compatibility policy](/widget/versions).
