> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Displaying & Updating User Info

<Card title="Recommended: JavaScript SDK with React Hooks" icon="react" color="#4779FE">
  For new React apps, we recommend the JavaScript SDK with React Hooks (`@dynamic-labs-sdk/react-hooks`) instead of the legacy React SDK documented here. The JS SDK comes with many benefits such as a much smaller bundle size and other optimizations. Use the [React quickstart (JavaScript SDK)](/javascript/reference/react-quickstart) to get started.
</Card>

## Using our UI

The Dynamic Widget UI component and Dynamic Embedded Widget UI component both contain a user profile section where the user can see their profile information and update it easily.

You can check it out at `https://demo.dynamic.xyz/`.

## Using your UI

This guide will help you to create a user profile inside your own custom UI, including everything you see in the regular [Dynamic Widget UI component](/react/reference/components/dynamicwidget)/[Dynamic Embedded Widget UI component](/react/reference/components/dynamicembeddedwidget) described above.

### Setup

#### Show the user's profile based on whether they are logged in or not

How: Check if the user is logged in or not

Hook/Component: [useIsLoggedIn](/react/reference/hooks/login-user-management/useisloggedin)

Notes: We start here assuming you have signup/login implemented already

React provides the `useIsLoggedIn` hook to check authentication status and conditionally render components.

```tsx React theme={"system"}
import { useIsLoggedIn } from "@dynamic-labs/sdk-react-core";

const isLoggedIn = useIsLoggedIn();

return <>{isLoggedIn ? <Profile /> : </Login>}</>
```

### Profile Info

#### Show user profile information

How: Fetch info from user object on useDynamicContext

Hook/Component: [useDynamicContext](/react/reference/hooks/usedynamiccontext)

Notes: The format of the user can be found here: [userProfile](/react/reference/objects/userprofile). **For working with custom metadata fields and storing additional user data, see [User Metadata](/react/users/displaying-updating#working-with-user-metadata).**

React provides the `useDynamicContext` hook to access user information and display profile details.

```tsx React theme={"system"}
import { useDynamicContext } from "@dynamic-labs/sdk-react-core";

const { user } = useDynamicContext();

return (
  <div className="user-details">
    {user?.firstName && <p>First name: {user.firstName} </p>}
    {user?.email && <p>E-Mail: {user.email} </p>}
    {user?.alias && <p>Alias: {user.alias} </p>}
    {user?.lastName && <p>Last name: {user.lastName} </p>}
    {user?.jobTitle && <p>Job: {user.jobTitle} </p>}
    {user?.phoneNumber && <p>Phone: {user.phoneNumber} </p>}
    {user?.tShirtSize && <p>Tshirt size: {user.tShirtSize} </p>}
    {user?.team && <p>Team: {user.team} </p>}
    {user?.country && <p>Country: {user.country} </p>}
    {user?.username && <p>Username: {user.username} </p>}
    {user?.metadata && Object.keys(user.metadata).length > 0 && (
      <div>
        <h4>Custom Metadata Fields:</h4>
        <p><em>Additional user data and preferences stored in metadata</em></p>
        {Object.entries(user.metadata).map(([key, value]) => (
          <p key={key}><strong>{key}:</strong> {String(value)}</p>
        ))}
      </div>
    )}
  </div>
);
```

#### Allow user to update their profile information

**How:** `useUserUpdateRequest` and `useOtpVerificationRequest`

**Hook/Component:** [useUserUpdateRequest](/react/reference/hooks/login-user-management/useuserupdaterequest)

**Notes:** Use the appropriate verification flag: `isEmailVerificationRequired` for email changes; `isSmsVerificationRequired` for phone changes. Metadata updates and general text fields typically do not require OTP.

### Updating Email

```tsx React theme={"system"}
import { useUserUpdateRequest, useOtpVerificationRequest } from "@dynamic-labs/sdk-react-core";
import { useState } from "react";

const { updateUser } = useUserUpdateRequest();
const { verifyOtp } = useOtpVerificationRequest();

const [showVerifyEmailForm, setShowVerifyEmailForm] = useState(false);
const [loading, setLoading] = useState(false);

const onSubmitEmailUpdate = async (firstName: string, email: string, metadata?: Record<string, any>) => {
  try {
    setLoading(true);
    const { isEmailVerificationRequired } = await updateUser({ firstName, email, metadata });
    if (isEmailVerificationRequired) setShowVerifyEmailForm(true);
  } finally {
    setLoading(false);
  }
};

const onVerifyEmailOtp = async (verificationToken: string) => {
  try {
    setLoading(true);
    await verifyOtp(verificationToken); // Uses active email verification context
  } finally {
    setLoading(false);
    setShowVerifyEmailForm(false);
  }
};
```

### Updating Phone

```tsx React theme={"system"}
import { useUserUpdateRequest, useOtpVerificationRequest } from "@dynamic-labs/sdk-react-core";
import { useState } from "react";

const { updateUser } = useUserUpdateRequest();
const { verifyOtp } = useOtpVerificationRequest();

const [showVerifySmsForm, setShowVerifySmsForm] = useState(false);
const [loading, setLoading] = useState(false);

const onSubmitPhoneUpdate = async (firstName: string, phoneNumber: string, metadata?: Record<string, any>) => {
  try {
    setLoading(true);
    // phoneNumber should be E.164 format, e.g. +14155551234
    const { isSmsVerificationRequired } = await updateUser({ firstName, phoneNumber, metadata });
    if (isSmsVerificationRequired) setShowVerifySmsForm(true);
  } finally {
    setLoading(false);
  }
};

const onVerifySmsOtp = async (verificationToken: string) => {
  try {
    setLoading(true);
    await verifyOtp(verificationToken); // Uses active SMS verification context
  } finally {
    setLoading(false);
    setShowVerifySmsForm(false);
  }
};
```

### Updating Meta

```tsx React theme={"system"}
import { useUserUpdateRequest } from "@dynamic-labs/sdk-react-core";

const { updateUser } = useUserUpdateRequest();

const onSubmitMetadataOnly = async (metadata: Record<string, any>) => {
  // Updating only metadata typically does not require OTP
  await updateUser({ metadata });
};
```

### Updating General

```tsx React theme={"system"}
import { useUserUpdateRequest } from "@dynamic-labs/sdk-react-core";

const { updateUser } = useUserUpdateRequest();

const onSubmitGeneral = async (fields: { firstName?: string; lastName?: string; username?: string }) => {
  // General fields (no email/phone change) typically do not require OTP
  await updateUser(fields);
};
```

### Socials

#### Show users linked social accounts, allow linking/unlinking

How: useSocialAccounts hook from sdk-react-core

Hook/Component: [useSocialAccounts](/react/reference/hooks/login-user-management/usesocialaccounts)

Notes: None

Use the `useSocialAccounts` hook to manage social account linking and unlinking with a comprehensive UI component.

```tsx React theme={"system"}
import { useSocialAccounts } from "@dynamic-labs/sdk-react-core";
import { SocialIcon } from '@dynamic-labs/iconic';

const Avatar = ({ avatarUrl }) => {
  return (
    <div className="avatar">
      <img src={avatarUrl} alt="avatar" />
    </div>
  );
};

const Icon = ({ provider }) => {
  return (
    <div className="icon-container">
    <SocialIcon name={provider} />
    </div>
  );
};

const UserProfileSocialAccount = ({ provider }) => {
  const {
    linkSocialAccount,
    unlinkSocialAccount,
    isProcessing,
    isLinked,
    getLinkedAccountInformation,
  } = useSocialAccounts();

  const isProviderLinked = isLinked(provider);
  const connectedAccountInfo = getLinkedAccountInformation(provider);

  return (
    <div className="social-account">
      <div className="icon">
        {isProviderLinked ? (
          <Avatar avatarUrl={connectedAccountInfo?.avatar} />
        ) : (
          <Icon provider={provider} />
        )}
      </div>
      <div className="label">
        <p>{isProviderLinked ? connectedAccountInfo?.publicIdentifier : provider}</p>
      </div>
      {isProviderLinked ? (
        <button
          onClick={() => unlinkSocialAccount(provider)}
          disabled={isProcessing}
        >
          Disconnect
        </button>
      ) : (
        <button
          onClick={() => linkSocialAccount(provider)}
          disabled={isProcessing}
        >
          Connect
        </button>
      )}
    </div>
  );
};

const Socials = () => {
  const providers = [
    "discord",
    "facebook",
    "github",
    "google",
    "instagram",
    "twitch",
    "twitter",
  ];

  return (
    <div className="social-accounts">
      {providers.map((provider) => (
        <UserProfileSocialAccount key={provider} provider={provider} />
      ))}
    </div>
  );
};
```

## Working with User Metadata

**User metadata provides a powerful way to store additional information beyond the standard profile fields.** This is perfect for storing user preferences, application state, custom attributes, and integration data.

### What is Metadata?

Metadata is a flexible key-value storage system that allows you to:

* Store user preferences (theme, language, notification settings)
* Track application state (onboarding progress, feature flags)
* Store business-specific data (subscription tiers, referral codes)
* Maintain integration data (external service IDs, webhook configs)

### Metadata Examples

```typescript theme={"system"}
// User preferences
metadata: {
  theme: 'dark',
  language: 'en',
  notifications_enabled: true
}

// Application state
metadata: {
  onboarding_completed: true,
  feature_flags: ['beta_features', 'advanced_analytics']
}

// Business data
metadata: {
  subscription_tier: 'premium',
  referral_code: 'USER123',
  last_purchase_date: '2024-01-15'
}
```

### Best Practices

* Size limit: Metadata is limited to 2KB total
* Key naming: Use descriptive, lowercase keys with underscores
* Value types: Supports strings, numbers, booleans, and nested objects
* Validation: Always validate on your backend before storing

<Tip>
  For how to add metadata to the user and update it, see [Custom Information Capture](/react/custom-fields/overview).
</Tip>

* Updated the “Allow user to update their profile information” section with distinct “Updating Email”, “Updating Phone”, “Updating Meta”, and “Updating General” subsections for both React and React Native, and used `isSmsVerificationRequired` for phone updates.
