TeraiTerai
React nativeReferences

useFormat

React hook that provides internationalized formatting functions for numbers, dates, lists, and more in React Native.

React hook that provides internationalized formatting functions for numbers, dates, lists, and more using the JavaScript Intl API in React Native.

import { View, Text } from 'react-native'
import { useFormat } from '@terai/react-native'

function Component() {
  const format = useFormat()

  return (
    <View>
      <Text>{format.number(1234.56, { style: 'currency', currency: 'USD' })}</Text>
      <Text>{format.date(new Date(), { dateStyle: 'long' })}</Text>
    </View>
  )
}

Return Value

Returns an object with formatting functions that automatically use the current locale:

number

Format numbers with locale-aware formatting.

  • Type: (value: number, options?: Intl.NumberFormatOptions) => string

Examples:

const format = useFormat()

// Currency
format.number(1234.56, { style: 'currency', currency: 'USD' })
// Result: '$1,234.56' (en), '1.234,56 $' (es), etc.

// Percentage
format.number(0.85, { style: 'percent' })
// Result: '85%'

// Compact notation
format.number(1234567, { notation: 'compact' })
// Result: '1.2M' (en), '1,2 M' (es), etc.

// Custom decimal places
format.number(3.14159, { minimumFractionDigits: 2, maximumFractionDigits: 4 })
// Result: '3.1416'

date

Format dates with locale-aware formatting.

  • Type: (value: Date | number, options?: Intl.DateTimeFormatOptions) => string

Examples:

const format = useFormat()
const date = new Date('2024-03-15')

// Long date style
format.date(date, { dateStyle: 'long' })
// Result: 'March 15, 2024' (en), '15 de marzo de 2024' (es)

// Custom format
format.date(date, {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  weekday: 'long'
})
// Result: 'Friday, March 15, 2024' (en)

// Time only
format.date(new Date(), { timeStyle: 'short' })
// Result: '2:30 PM' (en), '14:30' (es)

// Date and time
format.date(new Date(), {
  dateStyle: 'short',
  timeStyle: 'short'
})
// Result: '3/15/24, 2:30 PM' (en)

list

Format lists with locale-aware conjunctions and separators.

  • Type: (value: Iterable<string>, options?: Intl.ListFormatOptions) => string

Examples:

const format = useFormat()
const items = ['apples', 'oranges', 'bananas']

// Default (conjunction)
format.list(items)
// Result: 'apples, oranges, and bananas' (en), 'apples, oranges y bananas' (es)

// Disjunction
format.list(items, { type: 'disjunction' })
// Result: 'apples, oranges, or bananas' (en)

// Unit
format.list(['5 pounds', '12 ounces'], { type: 'unit' })
// Result: '5 pounds, 12 ounces' (en)

relativeTime

Format relative time with locale-aware phrases.

  • Type: (value: [number, Intl.RelativeTimeFormatUnit], options?: Intl.RelativeTimeFormatOptions) => string

Examples:

const format = useFormat()

// Past
format.relativeTime([-3, 'day'])
// Result: '3 days ago' (en), 'hace 3 días' (es)

// Future
format.relativeTime([2, 'hour'])
// Result: 'in 2 hours' (en), 'dentro de 2 horas' (es)

// Narrow style
format.relativeTime([-1, 'week'], { style: 'narrow' })
// Result: '1 wk. ago' (en)

// Auto numeric (uses 'yesterday', 'tomorrow', etc.)
format.relativeTime([-1, 'day'], { numeric: 'auto' })
// Result: 'yesterday' (en), 'ayer' (es)

displayNames

Format display names for languages, regions, currencies, etc.

  • Type: (value: string, options: Intl.DisplayNamesOptions) => string | undefined

Examples:

const format = useFormat()

// Language names
format.displayNames('es', { type: 'language' })
// Result: 'Spanish' (en), 'español' (es)

// Region names
format.displayNames('US', { type: 'region' })
// Result: 'United States' (en), 'Estados Unidos' (es)

// Currency names
format.displayNames('USD', { type: 'currency' })
// Result: 'US Dollar' (en), 'dólar estadounidense' (es)

// Script names
format.displayNames('Arab', { type: 'script' })
// Result: 'Arabic' (en)

Options

locale

  • Type: Locale | undefined
  • Default: Current locale from useLocale()

Override the locale for formatting. Useful when you need to format in a different locale than the current one.

const format = useFormat({ locale: 'es' })

// Always formats in Spanish, regardless of current locale
format.number(1234.56, { style: 'currency', currency: 'EUR' })
// Result: '1.234,56 €'

Use Cases

Price Display

import { View, Text, StyleSheet } from 'react-native'
import { useFormat } from '@terai/react-native'

function PriceTag({ amount, currency }) {
  const format = useFormat()

  return (
    <View style={styles.container}>
      <Text style={styles.price}>
        {format.number(amount, { style: 'currency', currency })}
      </Text>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    padding: 8,
  },
  price: {
    fontSize: 24,
    fontWeight: 'bold',
  },
})

Event Date Display

import { View, Text } from 'react-native'
import { useFormat } from '@terai/react-native'

function EventDate({ startDate, endDate }) {
  const format = useFormat()

  return (
    <View>
      <Text>
        {format.date(startDate, { dateStyle: 'medium' })}
        {' - '}
        {format.date(endDate, { dateStyle: 'medium' })}
      </Text>
    </View>
  )
}

Shopping Cart Summary

import { View, Text, StyleSheet } from 'react-native'
import { useFormat, useTs } from '@terai/react-native'

function CartSummary({ items, total, currency }) {
  const format = useFormat()
  const { ts } = useTs()

  return (
    <View style={styles.container}>
      <Text style={styles.items}>
        {format.list(items.map(item => item.name))}
      </Text>
      <Text style={styles.total}>
        {ts`Total`}: {format.number(total, { style: 'currency', currency })}
      </Text>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    padding: 16,
    backgroundColor: '#f5f5f5',
    borderRadius: 8,
  },
  items: {
    fontSize: 14,
    marginBottom: 8,
  },
  total: {
    fontSize: 18,
    fontWeight: 'bold',
  },
})

Post Timestamp

import { Text } from 'react-native'
import { useFormat } from '@terai/react-native'

function PostTimestamp({ createdAt }) {
  const format = useFormat()
  const now = Date.now()
  const diff = createdAt - now

  // Calculate appropriate unit
  const minutes = Math.floor(diff / 60000)
  const hours = Math.floor(diff / 3600000)
  const days = Math.floor(diff / 86400000)

  let value: [number, Intl.RelativeTimeFormatUnit]
  if (Math.abs(days) >= 1) {
    value = [days, 'day']
  } else if (Math.abs(hours) >= 1) {
    value = [hours, 'hour']
  } else {
    value = [minutes, 'minute']
  }

  return <Text>{format.relativeTime(value, { numeric: 'auto' })}</Text>
}

Language Selector Display

import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'
import { useFormat, useLocale, setLocale } from '@terai/react-native'

const LANGUAGES = ['en', 'es', 'fr', 'de', 'ja']

function LanguageSelector() {
  const format = useFormat()
  const currentLocale = useLocale()

  return (
    <View style={styles.container}>
      {LANGUAGES.map((lang) => (
        <TouchableOpacity
          key={lang}
          style={[
            styles.option,
            currentLocale === lang && styles.selectedOption,
          ]}
          onPress={() => setLocale(lang)}
        >
          <Text style={styles.optionText}>
            {format.displayNames(lang, { type: 'language' })}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    padding: 16,
  },
  option: {
    padding: 12,
    borderRadius: 8,
    marginBottom: 8,
    backgroundColor: '#f5f5f5',
  },
  selectedOption: {
    backgroundColor: '#e3f2fd',
  },
  optionText: {
    fontSize: 16,
  },
})

Performance

  • Formatting functions are locale-aware and automatically update when locale changes
  • Uses native Intl API for optimal performance
  • Memoized internally to prevent unnecessary recreations

React Native Considerations

The Intl API is available in React Native through:

  • Hermes: Full Intl support in recent versions
  • JavaScriptCore: Limited Intl support, may need polyfills
  • Android: Ensure Android API level 24+ for full Intl support

For older Android versions or JSC, consider using a polyfill like @formatjs/intl-* packages.

Requirements

  • Must be called inside a React component
  • Requires setupTerai to be called first
  • Requires Intl API support (Hermes recommended)