# React quickstart

> @tryyoursize/react: a provider near the root and element components where you need them. SSR-safe.

Source: https://docs.tryyoursize.com/quickstarts/react/

> **For your developer**
>
> **What it does:** Adds TryYourSize components to our React storefront: a size guide next to the size picker and the recommended size in our own labels. We receive sizes only.
>
> **Time needed:** An afternoon.
>
> **What to send them:** The publishable key (pk_test_…) and our site origins to register in Studio.

The components work like `@stripe/react-stripe-js`: one provider near the root of your app, and element components where you want them.

```bash
npm install @tryyoursize/react @tryyoursize/sdk
```

## Quick start

```tsx

// Once, outside render, so you don't create a new client on every render.
const tysPromise = loadTryYourSize("pk_test_…");

  return (
    <TryYourSizeProvider client={tysPromise} options={{ appearance: { variables: { borderRadius: 4 } } }}>
      <ProductPage />
    </TryYourSizeProvider>
  );
}

function ProductPage() {
  const [size, setSize] = useState<string | null>(null);
  return (
    <>
      <SizePicker value={size} onChange={setSize} />
      <FitElement product="SKU-123" onSize={({ size }) => setSize(size)} />
    </>
  );
}
```

If you bundle the SDK from npm instead of loading it from our CDN, pass the key: `<TryYourSizeProvider publishableKey="pk_test_…">`.

## `<TryYourSizeProvider>`

| Prop | |
|---|---|
| `publishableKey` | Your publishable key. The provider creates the client in the browser. |
| `client` | Instead of `publishableKey`, a client or a promise of one (for example `loadTryYourSize()`). `null` means "not yet": elements wait. |
| `options.appearance` | See [Appearance](https://docs.tryyoursize.com/guides/appearance.md). Changes apply live; an inline object does not cause updates on every render. |
| `options.locale` | `"auto"` or a language. Read once, when the client is created. |

The client cannot change after it is set; if it changes, the provider logs a warning and keeps the first client.

## Components

- **`<SizeGuide>`**: the link-sized size guide, next to your size picker. `variant="link"` or `"button"`.
- **`<FitElement>`**: the inline element (recommended). **`<FitButton>`**: the compact "Find my size" button.

| Prop | |
|---|---|
| `product` (required) | Your product ID or SKU. Changing it calls `update({ product })`, not a new element. |
| `onSize` | `({ product, size, verified }) => void`: the shopper chose a size in our window. |
| `onRecommendation` | `({ product, status, size, studioSize, wearableSizes }) => void`. See [Recommended size](https://docs.tryyoursize.com/guides/recommendation-event.md). |
| `onReady`, `onOpen`, `onClose`, `onLoadError` | The SDK events with the same names. |
| `id`, `className`, `style` | Applied to the mount `<div>`. |

```tsx
<SizeGuide
  product="SKU-123"
  onRecommendation={({ status, size }) => status === "ready" && !touched && setSize(size!)}
/>
```

A `ref` gives you `{ open(), close(), getElement() }`:

```tsx
const fit = useRef<ElementHandle>(null);
<button onClick={() => fit.current?.open()}>Measure me</button>
<FitElement ref={fit} product="SKU-123" />
```

## Hooks

- `useTryYourSize()` returns the client, or `null` until it has loaded. Use it for the client methods, for example `await tys.recommendationHandle()` to send a sealed handle to your server ([Server-side recommendations](https://docs.tryyoursize.com/guides/server-side-recommendations.md)).
- `useElements()` returns the provider's elements group, or `null` until loaded: use it for `elements.update({ appearance })`.

## Guarantees

- **Mount on commit, destroy on unmount.** Under `<StrictMode>` only one iframe is ever live.
- **SSR-safe.** Importing and server rendering never touch `window`; on the server you get an empty mount `<div>`.
- **Stable handlers.** Changing an event handler never reloads the iframe.
