Cómo formatear cantidades monetarias en TanStack Start v1

Muestra precios con símbolos de moneda y separadores

Problema

Los precios combinan dos desafíos de localización: representación de moneda y formato de números. El mismo valor monetario aparece como $1,200.50 en Estados Unidos y 1 200,50 € en Alemania. El símbolo de moneda se mueve, los separadores decimales y de agrupación se intercambian, e incluso el espaciado cambia.

Estas convenciones no son preferencias sino expectativas. Mostrar precios en un formato desconocido hace que los usuarios cuestionen si están viendo la cantidad correcta. Un precio mostrado como "1200.50 EUR" a un usuario alemán o "1.200,50$" a un usuario estadounidense crea fricción y erosiona la confianza.

Solución

Formatea valores monetarios basándote tanto en la moneda como en la configuración regional del usuario. Esto combina la ubicación del símbolo de moneda con las reglas de formato de números específicas de la configuración regional, creando precios que coinciden con las expectativas regionales de cómo debería verse el dinero.

Usa el método formatNumber de react-intl con la opción style: 'currency' para aplicar tanto el código de moneda como las convenciones de formato de la configuración regional del usuario. La API Intl.NumberFormat del navegador maneja automáticamente la ubicación del símbolo, la elección de separadores y el espaciado.

Pasos

1. Crea un componente de formato de moneda

Construye un componente reutilizable que acepte un valor numérico y un código de moneda, luego formatea el precio usando la configuración regional del usuario.

import { useIntl } from "react-intl";

interface PriceProps {
  value: number;
  currency: string;
}

export function Price({ value, currency }: PriceProps) {
  const intl = useIntl();

  const formattedPrice = intl.formatNumber(value, {
    style: "currency",
    currency: currency,
  });

  return <span>{formattedPrice}</span>;
}

El hook useIntl proporciona acceso a la API de formato. El método formatNumber con style: 'currency' aplica tanto el símbolo de moneda como el formato de números específico de la configuración regional.

2. Usa el componente con diferentes monedas

Muestra precios en toda tu aplicación pasando la cantidad numérica y el código de moneda.

export default function ProductCard() {
  return (
    <div>
      <h2>Premium Plan</h2>
      <Price value={1200.5} currency="USD" />
    </div>
  );
}

El componente formatea automáticamente el precio según la configuración regional del usuario. Un usuario estadounidense ve "$1,200.50" mientras que un usuario alemán ve "1.200,50 $".

3. Formatear precios con precisión decimal personalizada

Controla el número de decimales mostrados añadiendo las opciones minimumFractionDigits y maximumFractionDigits.

export function PriceWithPrecision({ value, currency }: PriceProps) {
  const intl = useIntl();

  const formattedPrice = intl.formatNumber(value, {
    style: "currency",
    currency: currency,
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  });

  return <span>{formattedPrice}</span>;
}

Esto garantiza una visualización decimal consistente en todos los precios, incluso cuando el valor es un número entero como 100.

4. Crear un helper para formateo en línea

Para casos donde un componente wrapper es innecesario, crea una función helper de formateo.

import { useIntl } from "react-intl";

export function useFormatCurrency() {
  const intl = useIntl();

  return (value: number, currency: string) => {
    return intl.formatNumber(value, {
      style: "currency",
      currency: currency,
    });
  };
}

Utiliza este hook cuando necesites precios formateados en atributos, valores computados u otros contextos que no sean JSX.

export function CheckoutSummary({ total }: { total: number }) {
  const formatCurrency = useFormatCurrency();

  return (
    <button aria-label={`Pay ${formatCurrency(total, "USD")}`}>Checkout</button>
  );
}

El helper devuelve una cadena de texto simple adecuada para cualquier contexto donde no se puedan usar componentes JSX.