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/.
Like with all this series of headless guides, “headless” is defined a way to use the Dynamic SDK without the need for Dynamic UI components (i.e. DynamicWidget, DynamicUserProfile).You still need to add the SDK and set up the Dynamic Context Provider (complete the quickstart if you haven’t done so already, or refer to an example app)
How: Fetch info from user object on useDynamicContextHook/Component: useDynamicContextNotes: The format of the user can be found here: userProfile. For working with custom metadata fields and storing additional user data, see User Metadata.
How: useUserUpdateRequest hookHook/Component: useUserUpdateRequestNotes: We include the validation for email updates here. This hook also supports updating custom metadata fields for storing additional user data.
Copy
Ask AI
import { useUserUpdateRequest, useOtpVerificationRequest } from "@dynamic-labs/sdk-react-core";import { useState } from "react";const { verifyOtp } = useOtpVerificationRequest();const { updateUser } = useUserUpdateRequest();const [showUpdateForm, setShowUpdateForm] = useState(false);const [showVerifyForm, setShowVerifyEmailForm] = useState(false);const [loading, setLoading] = useState(false);const updateUserInfoFormSubmit = async (e) => { e.preventDefault(); try { setLoading(true); // Parse custom field input (format: key:value) const customFieldInput = e.target[2].value; let metadata = {}; if (customFieldInput && customFieldInput.includes(':')) { const [key, value] = customFieldInput.split(':'); if (key.trim() && value.trim()) { metadata[key.trim()] = value.trim(); } } // Call the updateUser function with the new values entered by the user const { isEmailVerificationRequired } = await updateUser({ firstName: e.target[0].value, email: e.target[1].value, metadata: Object.keys(metadata).length > 0 ? metadata : undefined, }); // If email verification is required, show the email verification form if (isEmailVerificationRequired) { setShowVerifyEmailForm(true); } } catch (e) { console.log("Error", e); setLoading(false); } finally { setLoading(false); setShowUpdateForm(false); } }; // Handler for the email verification form submission const onVerifyEmailFormSubmit = async (e) => { e.preventDefault(); try { setLoading(true); const verificationToken = e.target[0].value; // Call the verifyEmail function with the entered verification token await verifyOtp(verificationToken); } catch (e) { console.log("Error", e); setLoading(false); } finally { setLoading(false); // Hide the email verification form after the process is completed setShowVerifyEmailForm(false); } return false; };return ( <div> {/* Render the profile update form */} {showUpdateForm && ( <div> <form onSubmit={updateUserInfoFormSubmit} className="form"> <div className="form__row"> <label className="label" htmlFor="firstName"> First-Name </label> <input id="firstName" className="form__input" defaultValue={user.firstName} disabled={loading || showVerifyEmailForm} /> </div> <div className="form__row"> <label className="label" htmlFor="email"> E-Mail </label> <input type="email" id="email" className="form__input" defaultValue={user.email} disabled={loading || showVerifyEmailForm} /> </div> <div className="form__row"> <label className="label" htmlFor="customField"> Custom Metadata Field (Key:Value) </label> <input id="customField" className="form__input" placeholder="e.g., favoriteColor:blue, subscriptionTier:premium" disabled={loading || showVerifyEmailForm} /> <small className="form__help"> Store additional user data like preferences, settings, or custom attributes </small> </div> <button disabled={loading || showVerifyEmailForm} className="form__button" type="submit" > Save </button> </form> </div> )} {/* Render the email verification form if needed */} {showVerifyEmailForm && ( <form onSubmit={onVerifyEmailFormSubmit} className="form"> <h6>Verify Email</h6> <div className="form__row"> <label htmlFor="verificationToken">Verification Token</label> <input disabled={loading} pattern="^\d{6}$" name="verificationToken" /> </div> <button disabled={loading} className="form__button" type="submit"> Send </button> </form> )} </div> );
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.