> ## 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.

# User profile & settings

> Display the signed-in user, edit profile fields, verify email or phone changes, and delete the account.

## Prerequisites

Before this page: a signed-in user (see [Email & SMS OTP sign-in](https://docs.dynamic.xyz/docs/javascript/building-ui/email-sms-otp-sign-in.md)).

## What you'll build

* **Display** the current user's profile.
* **Edit** profile fields like name and username.
* **Verify** a new email or phone number with a one-time code.
* **Delete** the account.

## Reading the profile

`useUser` returns a query result (`{ data: user, ... }`) that re-renders on any change — read the user from `data`. Outside React, read `getDefaultClient().user`.

> [tab] TypeScript
>
> ```typescript theme={"system"}
> import { getDefaultClient } from '@dynamic-labs-sdk/client';
>
> function renderProfile(el: HTMLElement) {
>   const user = getDefaultClient().user;
>   if (!user) return;
>   el.textContent = `${user.firstName ?? ''} ${user.lastName ?? ''}`.trim();
> }
> ```

> [tab] React
>
> ```tsx theme={"system"}
> import { useUser } from '@dynamic-labs-sdk/react-hooks';
>
> function Profile() {
>   const { data: user } = useUser();
>   if (!user) return null;
>   return <p>{`${user.firstName ?? ''} ${user.lastName ?? ''}`.trim()}</p>;
> }
> ```

## Updating profile fields

`updateUser` accepts the fields you want to change. Most fields save immediately. Changing **email** or **phone number** returns an `OTPVerification` — prompt for the code and confirm it with `verifyOTP`.

> [tab] TypeScript
>
> ```typescript theme={"system"}
> import { updateUser, verifyOTP } from '@dynamic-labs-sdk/client';
> import type { UpdateUserFields } from '@dynamic-labs-sdk/client';
>
> async function saveProfile(userFields: UpdateUserFields) {
>   const otpVerification = await updateUser({ userFields });
>
>   // No verification needed — the update is already saved.
>   if (!otpVerification) return;
>
>   // The code is sent to whichever contact changed: `email` is set for an
>   // email change, `phoneNumber` (with country code) for a phone change.
>   const sentToEmail = Boolean(otpVerification.email);
>   const destination = sentToEmail
>     ? otpVerification.email
>     : `${otpVerification.phoneCountryCode ?? ''}${otpVerification.phoneNumber ?? ''}`;
>
>   // promptForCode is your implementation — tell the user where to look.
>   const verificationToken = await promptForCode(destination);
>   await verifyOTP({ otpVerification, verificationToken });
> }
> ```

> [tab] React
>
> ```tsx theme={"system"}
> import { verifyOTP } from '@dynamic-labs-sdk/client';
> import { useUpdateUser } from '@dynamic-labs-sdk/react-hooks';
>
> function EditProfile() {
>   const { mutateAsync: update, isPending } = useUpdateUser();
>
>   return (
>     <form
>       onSubmit={async (event) => {
>         event.preventDefault();
>         const form = new FormData(event.currentTarget);
>         const otpVerification = await update({
>           userFields: {
>             firstName: String(form.get('firstName')),
>             username: String(form.get('username')),
>           },
>         });
>         if (otpVerification) {
>           // `email` is set for an email change, `phoneNumber` for a phone change.
>           const destination =
>             otpVerification.email ?? otpVerification.phoneNumber;
>           // promptForCode is your implementation — tell the user where to look.
>           const verificationToken = await promptForCode(destination);
>           await verifyOTP({ otpVerification, verificationToken });
>         }
>       }}
>     >
>       <input name="firstName" />
>       <input name="username" />
>       <button type="submit" disabled={isPending}>Save</button>
>     </form>
>   );
> }
> ```

> [!NOTE]
>
> Only send the fields you actually changed. Updatable fields include `firstName`, `lastName`, `username`, `alias`, `email`, `phoneNumber`, `country`, and `metadata`.

## Deleting the account

Offer account deletion from settings. Confirm clearly first — it's irreversible.

> [tab] TypeScript
>
> ```typescript theme={"system"}
> import { deleteUser } from '@dynamic-labs-sdk/client';
>
> async function removeAccount() {
>   // confirmDeletion is your implementation — require an explicit confirmation.
>   if (!(await confirmDeletion())) return;
>   await deleteUser();
> }
> ```

> [tab] React
>
> ```tsx theme={"system"}
> import { useState } from 'react';
> import { useDeleteUser } from '@dynamic-labs-sdk/react-hooks';
>
> function DeleteAccount() {
>   const { mutateAsync: remove, isPending } = useDeleteUser();
>   const [confirmed, setConfirmed] = useState(false);
>
>   if (!confirmed) {
>     return (
>       <button type="button" onClick={() => setConfirmed(true)}>
>         Delete account
>       </button>
>     );
>   }
>
>   return (
>     <div>
>       <p>This is permanent. Delete your account?</p>
>       <button type="button" onClick={() => setConfirmed(false)}>
>         Cancel
>       </button>
>       <button type="button" disabled={isPending} onClick={() => remove()}>
>         {isPending ? 'Deleting…' : 'Confirm delete'}
>       </button>
>     </div>
>   );
> }
> ```

## Handling errors

| Situation | What to do |
| - | - |
| `updateUser` returns an `OTPVerification` | Email/phone changed — collect the code and call `verifyOTP` to confirm. |
| Wrong verification code | `verifyOTP` rejects — ask the user to re-enter the code sent to the new contact. |
| Username/email already taken | Surface the field-level error and let the user pick another value. |
| Account deletion confirmed | The user is signed out — route them to your signed-out landing page. |

## See also

* [Account merging](https://docs.dynamic.xyz/docs/javascript/building-ui/account-merging.md) — combine two accounts into one
* [Step-up authentication](https://docs.dynamic.xyz/docs/javascript/building-ui/step-up-authentication.md) — require MFA before a profile update
* [Post-login user setup](https://docs.dynamic.xyz/docs/javascript/building-ui/post-auth-user-setup.md) — collect required profile fields right after sign-in


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.