# useCoupon (https://docs.salla.dev/twilight/react/hooks/use-coupon)



Use `useCoupon` to build a coupon box on your cart page: an input that applies a code, and a button that removes it.

## Example [#example]

```tsx title="app/components/cart/CouponBox.tsx"
import { useState } from 'react';
import { useCoupon } from '@salla.sa/twilight-theme-engine/hooks/useCoupon';

export function CouponBox({ applied }: { applied?: string | null }) {
  const { apply, remove, loading, error } = useCoupon();
  const [code, setCode] = useState('');

  if (applied) {
    return (
      <div>
        <span>Coupon: {applied}</span>
        <button onClick={remove} disabled={loading}>Remove</button>
      </div>
    );
  }

  return (
    <div>
      <input value={code} onChange={(e) => setCode(e.target.value)} />
      <button onClick={() => apply(code)} disabled={loading}>Apply</button>
      {error && <p role="alert">{error}</p>}
    </div>
  );
}
```

Pass the applied code from the cart: `cart.coupon`. See [Cart data](https://docs.salla.dev/twilight/react/data/cart).

## API [#api]

```ts
function useCoupon(): UseCouponResult;

interface UseCouponResult {
  value: string | null;
  loading: boolean;
  error: string | null;
  apply: (code: string) => Promise<boolean>;
  remove: () => Promise<boolean>;
}
```

| Prop      | Type                                 | Description                                                                                                         |
| --------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `value`   | `string \| null`                     | The code this hook applied, or `null`.                                                                              |
| `loading` | `boolean`                            | `true` while `apply` or `remove` runs.                                                                              |
| `error`   | `string \| null`                     | The message of the last failure, or `null`.                                                                         |
| `apply`   | `(code: string) => Promise<boolean>` | Trims the code and adds it to the cart with `salla.cart.addCoupon`. Resolves `true` on success, `false` on failure. |
| `remove`  | `() => Promise<boolean>`             | Removes the coupon with `salla.cart.deleteCoupon`. Resolves `true` on success, `false` on failure.                  |

## Gotchas [#gotchas]

* The hook changes the cart through the [Salla SDK](https://docs.salla.dev/twilight/react/guide/salla-sdk-and-events), and the cart is updated on the server. The hook does not refetch your cart data: read the new totals and `cart.coupon` from the cart, see [Cart data](https://docs.salla.dev/twilight/react/data/cart).
* `value` is local state and starts as `null` on every page load, even when the cart already has a coupon. Read the applied code from `cart.coupon`, not from `value`.
* An empty or blank code fails with the error `Please enter a coupon code` (English only) and sends no request.
* Server errors (an invalid or expired code) arrive in `error` as the `message` of the error the SDK raised.
* `apply` and `remove` never throw. Check the boolean they resolve.
* Call them from event handlers, not during render: the hook is client-only, and it does nothing when the Salla SDK is not loaded yet.
* Store setting `settings.cart.apply_coupon_enabled` says whether the coupon box should be shown, see [Store data](https://docs.salla.dev/twilight/react/data/store).

## Next [#next]

* [Cart data](https://docs.salla.dev/twilight/react/data/cart): `cart.coupon`, totals and discounts.
* [`useAsyncFn`](https://docs.salla.dev/twilight/react/hooks/use-async-fn), the loading and error helper this hook is built on.
* [Cart page](https://docs.salla.dev/twilight/react/routes/cart)
