User data

The signed-in customer's profile from useUser(), its fields, and what you get for a guest.

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

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 API module (GET auth/user).

What useUser() returns

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

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:

FieldTypeDescription
isLoggedInbooleantrue when an auth token exists. It says nothing about whether the profile loaded or the token is still valid.
dataUser | nullThe profile. null for a guest, while loading, and when the request fails.
isLoadingbooleantrue while the profile request runs.
isFetchingbooleantrue 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

Example (illustrative values):

User object (illustrative values)
{ 13 }
:"user"always "user" for a profile you read through useUser
:42
:"Sara"
:"Ahmad"
:"sara@example.com"
:"+966500000000"
:"https://example.com/avatar.jpg"
:"SA"
:"female"
:nullnull when the customer did not set it
:1572707472Unix time in seconds
:{ 4 }
:[ 1 ]
Click a key to copy its path.

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

User

FieldTypeDescription
type"guest" | "user"Kind of customer. useUser only ever gives 'user'; a guest is null.
id?numberCustomer id.
first_name?stringFirst name.
last_name?stringLast name.
email?stringEmail address.
mobile?stringMobile number with the country prefix.
avatar?stringAvatar image URL.
country_code?stringCountry of the customer.
gender?stringGender as saved in the profile.
birthday?string | nullBirthday, or null.
created_at?numberWhen the account was created, as Unix seconds.
preferences?UserPreferencesThe customer's saved preferences.
social_accounts?UserSocialAccount[]Linked social sign-in accounts.

preferences

FieldTypeDescription
currency_code?stringCurrency the customer chose.
language_code?stringLanguage the customer chose.
currency?stringCurrency the customer chose, under the other key the API may use.
language?stringLanguage the customer chose, under the other key the API may use.
name_visiblebooleanWhether the customer's name is visible to others.
notifications_enabledbooleanWhether the customer accepts marketing messages.

social_accounts

FieldTypeDescription
provider_idstringThe customer's id at that provider.
providerstringProvider name, such as "google".
linkedbooleanWhether the account is currently linked.

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.

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.

Common tasks

Show the full name, with a fallback:

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:

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

Reload the profile after the customer edits it:

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

Reset the cached profile when the customer signs in or out, see the user API module.

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

On this page