# User data (https://docs.salla.dev/twilight/react/data/user)





Use this page when a component shows the customer's name, avatar or preferences, or must behave differently for guests and signed-in customers.

## Read it [#read-it]

```tsx title="app/components/layout/Greeting.tsx"
import { useUser } from '@salla.sa/twilight-theme-engine/hooks/useUser';

export function Greeting() {
  const { isLoggedIn, data: user } = useUser();

  if (!isLoggedIn) return <a href="/login">Sign in</a>;
  if (!user) return <span>...</span>; // signed in, profile not loaded yet
  return <span>Hello, {user.first_name}</span>;
}
```

`useUser` has no props. It reads the customer's auth token from the engine and, when there is one, fetches the profile with the [`user`](https://docs.salla.dev/twilight/react/api/modules/user) API module (`GET auth/user`).

## What `useUser()` returns [#what-useuser-returns]

The result is a React Query result for `User | null`, plus `isLoggedIn`:

```ts
type UseUserReturn = UseQueryResult<User | null> & {
  isLoggedIn: boolean;
};
```

The result is a standard React Query result, so it is not generated from the engine types. The fields you use most:

| Field         | Type                               | Description                                                                                                     |
| ------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `isLoggedIn`  | `boolean`                          | `true` when an auth token exists. It says nothing about whether the profile loaded or the token is still valid. |
| `data`        | `User \| null`                     | The profile. `null` for a guest, while loading, and when the request fails.                                     |
| `isLoading`   | `boolean`                          | `true` while the profile request runs.                                                                          |
| `isFetching`  | `boolean`                          | `true` on every fetch, including refetches.                                                                     |
| `fetchStatus` | `"idle" \| "fetching" \| "paused"` | `"idle"` for a guest, because the query is disabled without a token.                                            |
| `refetch`     | `() => Promise<...>`               | Loads the profile again, for example after the customer edits it.                                               |

The rest of the React Query result (`status`, `error`, `isError`, `isPlaceholderData`) is also there. `error` stays empty, because the API module turns every failure into `null`.

## The `User` object [#the-user-object]

Example (illustrative values):

<JsonExplorer data="userExample" title="User object (illustrative values)" defaultOpen="1" />

Every field except `type` is optional in the type. `created_at` is Unix seconds.

### User [#user]

{/* types: ../../../../../theme-engine/src/types/index.ts#User depth=2 */}

| Field              | Type                  | Description                                                          |
| ------------------ | --------------------- | -------------------------------------------------------------------- |
| `type`             | `"guest" \| "user"`   | Kind of customer. `useUser` only ever gives 'user'; a guest is null. |
| `id?`              | `number`              | Customer id.                                                         |
| `first_name?`      | `string`              | First name.                                                          |
| `last_name?`       | `string`              | Last name.                                                           |
| `email?`           | `string`              | Email address.                                                       |
| `mobile?`          | `string`              | Mobile number with the country prefix.                               |
| `avatar?`          | `string`              | Avatar image URL.                                                    |
| `country_code?`    | `string`              | Country of the customer.                                             |
| `gender?`          | `string`              | Gender as saved in the profile.                                      |
| `birthday?`        | `string \| null`      | Birthday, or null.                                                   |
| `created_at?`      | `number`              | When the account was created, as Unix seconds.                       |
| `preferences?`     | `UserPreferences`     | The customer's saved preferences.                                    |
| `social_accounts?` | `UserSocialAccount[]` | Linked social sign-in accounts.                                      |

#### `preferences` [#preferences]

| Field                   | Type      | Description                                                       |
| ----------------------- | --------- | ----------------------------------------------------------------- |
| `currency_code?`        | `string`  | Currency the customer chose.                                      |
| `language_code?`        | `string`  | Language the customer chose.                                      |
| `currency?`             | `string`  | Currency the customer chose, under the other key the API may use. |
| `language?`             | `string`  | Language the customer chose, under the other key the API may use. |
| `name_visible`          | `boolean` | Whether the customer's name is visible to others.                 |
| `notifications_enabled` | `boolean` | Whether the customer accepts marketing messages.                  |

#### `social_accounts` [#social_accounts]

| Field         | Type      | Description                              |
| ------------- | --------- | ---------------------------------------- |
| `provider_id` | `string`  | The customer's id at that provider.      |
| `provider`    | `string`  | Provider name, such as "google".         |
| `linked`      | `boolean` | Whether the account is currently linked. |

{/* /types */}

## Guests [#guests]

A guest has no auth token, so:

* `isLoggedIn` is `false`, `data` is `null`, and no request is sent.
* A guest is `null`, never a `User` with `type: "guest"`.
* Do not count on the profile being in the server HTML. Render the guest version first and let `data` fill in.

<Callout type="warn">
  `isLoggedIn` can be `true` while `data` is `null`: the profile is still loading, or the token expired and the request failed. The API module cannot tell "guest" from "request failed", so show a neutral state, not an error.
</Callout>

## Common tasks [#common-tasks]

Show the full name, with a fallback:

```tsx
const { data: user } = useUser();
const name = [user?.first_name, user?.last_name].filter(Boolean).join(' ') || 'Guest';
```

Pick the customer's saved language, when there is one:

```tsx
const { data: user } = useUser();
const language = user?.preferences?.language_code;
```

Reload the profile after the customer edits it:

```tsx
const { refetch } = useUser();
await refetch();
```

Reset the cached profile when the customer signs in or out, see the [`user` API module](https://docs.salla.dev/twilight/react/api/modules/user).

## Gotchas [#gotchas]

* Do not use `data` to decide whether the customer is signed in. Use `isLoggedIn` for "is there a session" and `data` for "do I have the profile".
* `created_at` is seconds, not milliseconds. Use `new Date(user.created_at * 1000)`.
* Don't log the profile or put it in a page that is cached for other visitors; it is personal data.

## Next [#next]

* [`user` API module](https://docs.salla.dev/twilight/react/api/modules/user) for the request behind `useUser`.
* [Authentication and scope](https://docs.salla.dev/twilight/react/api/authentication-and-scope) for how the token reaches API calls.
* [Cart data](https://docs.salla.dev/twilight/react/data/cart) and the [Data overview](https://docs.salla.dev/twilight/react/data).
