---
title: useUser
description: "Access session-stable user information like locale and timezone in your app views."
---

The `useUser` hook returns session-stable user information. These values are set once at initialization and do not change during the session.

## Basic usage

```tsx
import { useUser } from "skybridge/web";

function UserInfo() {
  const { locale, userAgent } = useUser();

  return (
    <div>
      <p>Locale: {locale}</p>
      <p>Device: {userAgent.device.type}</p>
      <p>Touch: {userAgent.capabilities.touch ? "Yes" : "No"}</p>
    </div>
  );
}
```

## Returns

```tsx
type UserState = {
  locale: string;
  userAgent: UserAgent;
};

type UserAgent = {
  device: {
    type: "mobile" | "tablet" | "desktop" | "unknown";
  };
  capabilities: {
    hover: boolean;
    touch: boolean;
  };
};
```

### `locale`

The user's locale string in BCP 47 format (e.g., `"en-US"`, `"fr-FR"`, `"ja-JP"`).

### `userAgent`

Information about the user's device and its capabilities.

#### `userAgent.device.type`

The type of device the user is on:

- `mobile` - Mobile phone
- `tablet` - Tablet device
- `desktop` - Desktop or laptop computer
- `unknown` - Unable to determine device type

#### `userAgent.capabilities.hover`

Whether the device supports hover interactions (typically `true` for desktop, `false` for touch-only devices).

#### `userAgent.capabilities.touch`

Whether the device supports touch interactions.

## Examples

### Localized Greeting

```tsx
import { useUser } from "skybridge/web";

function LocalizedGreeting() {
  const { locale } = useUser();

  const greetings: Record<string, string> = {
    en: "Hello!",
    fr: "Bonjour!",
    es: "Hola!",
    de: "Hallo!",
    ja: "こんにちは!",
  };

  const language = locale.split("-")[0];
  const greeting = greetings[language] || greetings.en;

  return <h1>{greeting}</h1>;
}
```

### Date Formatting

```tsx
import { useUser } from "skybridge/web";

function LocalizedDate({ date }: { date: Date }) {
  const { locale } = useUser();

  const formattedDate = new Intl.DateTimeFormat(locale, {
    dateStyle: "full",
    timeStyle: "short",
  }).format(date);

  return <time dateTime={date.toISOString()}>{formattedDate}</time>;
}
```

### Number and Currency Formatting

```tsx
import { useUser } from "skybridge/web";

function PriceDisplay({ amount, currency }: { amount: number; currency: string }) {
  const { locale } = useUser();

  const formattedPrice = new Intl.NumberFormat(locale, {
    style: "currency",
    currency,
  }).format(amount);

  return <span className="price">{formattedPrice}</span>;
}
```

### Responsive Component

```tsx
import { useUser } from "skybridge/web";

function ResponsiveLayout({ children }: { children: React.ReactNode }) {
  const { userAgent } = useUser();

  const layoutClass = {
    mobile: "layout-compact",
    tablet: "layout-medium",
    desktop: "layout-full",
    unknown: "layout-full",
  }[userAgent.device.type];

  return <div className={layoutClass}>{children}</div>;
}
```

### Touch-Friendly Controls

```tsx
import { useUser } from "skybridge/web";

function Slider({ value, onChange }: { value: number; onChange: (v: number) => void }) {
  const { userAgent } = useUser();

  // Use larger touch targets on touch devices
  const thumbSize = userAgent.capabilities.touch ? 44 : 20;

  return (
    <input
      type="range"
      value={value}
      onChange={(e) => onChange(Number(e.target.value))}
      style={{
        height: thumbSize,
        cursor: userAgent.capabilities.hover ? "pointer" : "default",
      }}
    />
  );
}
```
