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

# React

> Mount one Connect.js instance in a React component and send the auth code to a backend.

Create the Connect instance in an effect, keep it in a ref, and call `open()` from the button. This prevents the widget from being recreated on every render.

## Account-linking component

```jsx theme={null}
import { useEffect, useRef, useState } from "react"
import Connect from "@mono.co/connect.js"

export function LinkAccountButton({ customerId }) {
  const connectRef = useRef(null)
  const [ready, setReady] = useState(false)

  useEffect(() => {
    const connect = new Connect({
      key: import.meta.env.VITE_MONO_PUBLIC_KEY,
      scope: "auth",
      data: {
        customer: { id: customerId }
      },
      onLoad: () => setReady(true),
      onSuccess: async ({ code }) => {
        const response = await fetch("/api/mono/exchange", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ code })
        })

        if (!response.ok) {
          throw new Error("Could not complete Mono account linking")
        }
      },
      onClose: () => console.log("Connect closed")
    })

    connect.setup()
    connectRef.current = connect

    return () => {
      connect.close()
      connectRef.current = null
    }
  }, [customerId])

  return (
    <button
      type="button"
      disabled={!ready}
      onClick={() => connectRef.current?.open()}
    >
      {ready ? "Link a financial account" : "Loading account linking…"}
    </button>
  )
}
```

Replace the Vite environment-variable syntax if your build tool uses a different public-variable convention. Only the Mono public key belongs in the client bundle.

## Reauthorization

Use the stored Mono account ID and call `reauthorise()` instead of `setup()`.

```javascript theme={null}
useEffect(() => {
  const connect = new Connect({
    key: import.meta.env.VITE_MONO_PUBLIC_KEY,
    scope: "auth",
    onSuccess: ({ code }) => sendReauthorizationResult(code)
  })

  connect.reauthorise(accountId)
  connectRef.current = connect

  return () => connect.close()
}, [accountId])
```

## React-specific checks

* Initialize inside `useEffect`, where the DOM is available.
* Store the instance in `useRef`; do not store it in render state.
* Include values used to configure the instance in the effect dependency list.
* Close the instance when the component unmounts.
* Keep secret-key exchange logic in a backend route.

For the server request, follow the [Quickstart](/content/quickstart). For payment-specific response handling, see [Direct debit](/content/sdk/connect-js/usage/direct-debit).
