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

# React

> Embed StackOne Hub in a React app using the <stackone-hub> custom element

Use the `<stackone-hub>` custom element from `@stackone/hub` directly in JSX. This is the right choice if you can't add another copy of React to your bundle, or if you want the same code path as your non-React surfaces.

<Note>
  If you're starting fresh in React, the [`<StackOneHub>` component](/guides/embedding-stackone-hub) is usually a better fit — it integrates with your React tree and lets you pass callbacks as props. Reach for the web component when you need the framework-agnostic build.
</Note>

<Steps>
  <Step title="Install the package">
    <CodeGroup>
      ```bash npm theme={null}
      npm install @stackone/hub
      ```

      ```bash yarn theme={null}
      yarn add @stackone/hub
      ```

      ```bash pnpm theme={null}
      pnpm add @stackone/hub
      ```
    </CodeGroup>
  </Step>

  <Step title="Register the element at app entry">
    The import is side-effecting — it registers `<stackone-hub>` on `customElements`.

    ```tsx theme={null}
    // src/main.tsx
    import '@stackone/hub/webcomponent';
    import { StrictMode } from 'react';
    import { createRoot } from 'react-dom/client';
    import App from './App';

    const root = document.getElementById('root');
    if (!root) {
      throw new Error('#root element not found');
    }
    createRoot(root).render(
      <StrictMode>
        <App />
      </StrictMode>,
    );
    ```
  </Step>

  <Step title="Type the element for JSX">
    Tell TypeScript that `<stackone-hub>` is a valid JSX tag:

    ```tsx theme={null}
    declare global {
      // biome-ignore lint/style/noNamespace: JSX intrinsic-element augmentation requires namespace syntax.
      namespace JSX {
        interface IntrinsicElements {
          'stackone-hub': React.DetailedHTMLProps<
            React.HTMLAttributes<HTMLElement> & {
              token?: string;
              mode?: string;
              'base-url'?: string;
              'app-url'?: string;
              'account-id'?: string;
              height?: string;
              theme?: string;
              'show-footer-links'?: boolean | string;
              'on-close-label'?: string;
            },
            HTMLElement
          >;
        }
      }
    }
    ```
  </Step>

  <Step title="Get a session token from your backend">
    <Snippet file="guides/web-component-token-step.mdx" />
  </Step>

  <Step title="Add the element and listen for events">
    React 19 passes unknown props through as attributes, but events still need to be wired with `addEventListener` via a `ref` — React doesn't synthesize custom DOM events.

    ```tsx theme={null}
    import { useEffect, useRef, useState } from 'react';

    export default function App() {
      const [token, setToken] = useState('');
      const hubRef = useRef<HTMLElement>(null);

      useEffect(() => {
        retrieveConnectSessionToken().then(setToken);
      }, []);

      useEffect(() => {
        const el = hubRef.current;
        if (!el) return;
        const onSuccess = (event: Event) => {
          const detail = (event as CustomEvent).detail;
          console.log('Connected:', detail.id, detail.provider);
        };
        const onClose = () => console.log('Closed');
        el.addEventListener('success', onSuccess);
        el.addEventListener('close', onClose);
        return () => {
          el.removeEventListener('success', onSuccess);
          el.removeEventListener('close', onClose);
        };
      }, []);

      return (
        <stackone-hub
          ref={hubRef}
          token={token || undefined}
          mode="integration-picker"
          height="600px"
        />
      );
    }
    ```
  </Step>
</Steps>

## Attribute reference

All scalar `StackOneHub` props map to kebab-case HTML attributes — see the [vanilla guide](/guides/web-component-vanilla#attribute-reference) for the full table.

## Events

Native DOM `CustomEvent`s on the element:

| Event     | `event.detail`                     |
| --------- | ---------------------------------- |
| `success` | `{ id: string; provider: string }` |
| `close`   | `undefined`                        |

React's `onSuccess={...}` JSX shorthand does **not** fire on native DOM `CustomEvent`s — React doesn't synthesize custom DOM events. Subscribe with `addEventListener` via a `ref` instead.

## Next steps

<CardGroup cols={2}>
  <Card title="Backend setup" icon="server" href="/platform/connect-your-backend-with-stackone">
    Generate session tokens from your backend.
  </Card>

  <Card title="React component path" icon="react" href="/guides/embedding-stackone-hub">
    Use <code>\<StackOneHub></code> instead, with native React props.
  </Card>
</CardGroup>
