Skip to content
Twilight React Playground
ثيم رائدaren

useMoney

hookBeginnerserverbrowserlive demo

Formats prices in the page language (with the riyal icon for SAR), and parses or validates amounts.

import { useMoney, UseMoneyResult } from '@salla.sa/twilight-theme-engine/hooks/useMoney';

In plain words

Showing a price looks simple until you need two decimals, Arabic digits, and the Saudi riyal symbol. useMoney() does that for you: format(1250) becomes "1,250.00" followed by the riyal icon.

It also has parse, which turns a price string back into a number, and isValid, which checks whether a value is a usable amount.

Signature

function useMoney(): UseMoneyResult

interface UseMoneyResult {
  format: (
    amount: number | string | undefined,
    options?: { currency?: string; locale?: string; type?: 'product' | 'general' }
  ) => React.ReactNode;
  parse: (moneyString: string) => number;
  isValid: (value: unknown) => boolean;
}

Try it live

useMoney() formats the amount with the store settings the page was rendered with.Try this: set the currency to USD, then clear the amount and switch the type between product and general.
Storefront canvas · en · LTR

1,250.00

isValid(amount)
true
parse('1,250.50 SAR')
1250.5
Controls
A number or a numeric string. Try an empty value.
Only matters for an empty amount.
What a theme writes
import { useMoney } from '@salla.sa/twilight-theme-engine/hooks/useMoney';

export function Price() {
  const { format } = useMoney();
  return <span className="price">{format(1250)}</span>;
}

Example

app/components/Price.tsx
import { useMoney } from '@salla.sa/twilight-theme-engine/hooks/useMoney';

export function Price({ amount }: { amount: number }) {
  const { format } = useMoney();
  return <span className="price">{format(amount)}</span>;
}

How it behaves

  • format defaults to currency SAR, the page locale and type product, and always shows two decimals.

  • For SAR it returns markup, the number followed by <i className="sicon-sar" />. Any other currency goes through Intl.NumberFormat with style: currency, falling back to "1,250.00 XYZ" for a code Intl does not know.

  • An empty amount returns "-" when the store enables settings.product.show_price_as_dash and the type is product; otherwise an empty string.

  • Arabic digits are forced only when the store enables arabic_numbers_enabled and the locale starts with ar.

Gotchas

  • format returns a React node, not a string. format(100) + " SAR" or aria-label={format(100)} gives "[object Object]" for SAR. Render it as a child instead.

Related

Source and docs