> For the complete documentation index, see [llms.txt](https://docs.cspr.click/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cspr.click/cspr.click-sdk/integration/react-context-provider.md).

# React Context Provider

In React applications, you can wrap the SDK download and initialization flow in a context provider. This keeps the CSPR.click runtime reference and connected account state available to any component through a custom hook.

Use this approach when your application loads CSPR.click from the CDN but still wants React-friendly access to the SDK. If you are not using React, follow the lower-level [Downloading and initializing the SDK](https://github.com/make-software/casper-click-websdk/blob/master/docs/public/csprclick-sdk/downdload-and-initialize.md) guide instead.

## Create the provider

Create a `ClickContext.tsx` file and define the SDK options before the runtime script is loaded. The provider listens for the `csprclick:loaded` event, stores the SDK reference, and keeps the active account state synchronized with CSPR.click events.

```tsx
import { createContext, useContext, useEffect, useState } from 'react';
import type { ReactNode } from 'react';
import {
  CONTENT_MODE,
  WALLET_KEYS,
} from '@make-software/csprclick-core-types';
import type {
  AccountType,
  CsprClickInitOptions,
  ICSPRClickSDK,
} from '@make-software/csprclick-core-types';
import type { ClickUIOptions } from '@make-software/csprclick-core-types/clickui';

declare global {
  interface Window {
    clickUIOptions: ClickUIOptions;
    clickSDKOptions: CsprClickInitOptions;
    csprclick?: ICSPRClickSDK;
  }
}

window.clickUIOptions = {
  uiContainer: 'csprclick-ui',
  rootAppElement: '#root',
  show1ClickModal: true,
  showTopBar: true,
  accountMenuItems: [
    'AccountCardMenuItem',
    'CopyHashMenuItem',
    'BuyCSPRMenuItem',
  ],
  defaultTheme: 'light',
};

window.clickSDKOptions = {
  appName: 'CSPR.click React template',
  appId: 'csprclick-template',
  providers: [
    WALLET_KEYS.CASPER_WALLET,
    WALLET_KEYS.LEDGER,
    WALLET_KEYS.METAMASK_SNAP,
  ],
  contentMode: CONTENT_MODE.IFRAME,
};

type ClickContextState = {
  publicKey: string | undefined;
  provider: string | undefined;
  clickRef: ICSPRClickSDK | undefined;
};

type AccountChangedEvent = {
  account?: AccountType;
};

const ClickContext = createContext<ClickContextState | undefined>(undefined);

type ClickProviderProps = {
  children: ReactNode;
};

export const ClickProvider = ({ children }: ClickProviderProps) => {
  const [connectedAccount, setConnectedAccount] = useState<AccountType | undefined>();
  const [clickRef, setClickRef] = useState<ICSPRClickSDK | undefined>();

  useEffect(() => {
    const checkActiveAccount = async (ref: ICSPRClickSDK) => {
      try {
        const account = await ref.getActiveAccountAsync({
          withBalance: true,
          withFiatCurrency: 'USD',
        });

        setConnectedAccount(account?.public_key ? account : undefined);
      } catch (error) {
        console.error('Failed to get active account', error);
        setConnectedAccount(undefined);
      }
    };

    const handleAccountChanged = (event: AccountChangedEvent) => {
      const account = event.account;
      setConnectedAccount(account?.public_key ? account : undefined);
    };

    const handleSdkLoaded = () => {
      const ref = window.csprclick;

      if (!ref) {
        return;
      }

      setClickRef(ref);
      ref.on('csprclick:signed_in', handleAccountChanged);
      ref.on('csprclick:switched_account', handleAccountChanged);
      ref.on('csprclick:unsolicited_account_change', handleAccountChanged);
      ref.on('csprclick:signed_out', () => setConnectedAccount(undefined));
      checkActiveAccount(ref);
    };

    window.addEventListener('csprclick:loaded', handleSdkLoaded);

    if (window.csprclick) {
      handleSdkLoaded();
    }

    if (!document.querySelector('script#csprclick-client')) {
      const script = document.createElement('script');
      script.src = 'https://cdn.cspr.click/ui/v2.1.0/csprclick-client-2.1.0.js';
      script.id = 'csprclick-client';
      script.async = true;
      document.head.appendChild(script);
    }

    return () => {
      window.removeEventListener('csprclick:loaded', handleSdkLoaded);
    };
  }, []);

  return (
    <ClickContext.Provider
      value={{
        publicKey: connectedAccount?.public_key,
        provider: connectedAccount?.provider,
        clickRef,
      }}
    >
      {children}
    </ClickContext.Provider>
  );
};

export const useClickRef = (): ClickContextState => {
  const context = useContext(ClickContext);

  if (!context) {
    throw new Error('useClickRef must be used within a ClickProvider');
  }

  return context;
};
```

## Add the UI container

The CDN runtime still needs a DOM element where it can mount the CSPR.click top bar and modal UI. Add this container to your `index.html`, before the React root element.

```html
<body>
  <div id="csprclick-ui-wrapper">
    <div id="csprclick-ui"></div>
  </div>
  <div id="root">
    <!-- your React application goes here -->
  </div>
</body>
```

The container `id` must match the `uiContainer` value configured in `window.clickUIOptions`.

## Wrap your application

Wrap your application with `ClickProvider` so components can access the SDK reference and account state.

```tsx
import { ClickProvider } from './ClickContext';

createRoot(document.getElementById('root')!).render(
  <ClickProvider>
    <App />
  </ClickProvider>
);
```

## Use the SDK from a component

Call `useClickRef()` from any component rendered inside the provider. The `clickRef` value is available after the CDN runtime has loaded.

```tsx
import { useClickRef } from './ClickContext';

const ConnectButton = () => {
  const { clickRef, publicKey } = useClickRef();

  return (
    <button onClick={() => clickRef?.signIn()}>
      {publicKey ? 'Connected' : 'Connect wallet'}
    </button>
  );
};
```

## What's next

After the provider is in place, continue with the shared integration steps:

* [Handling events](/cspr.click-sdk/integration/handling-events.md)
* [Connecting a wallet](/cspr.click-sdk/integration/connecting-a-wallet.md)
* [Signing transactions](/cspr.click-sdk/integration/signing-transactions.md)
