
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
If you’re still thinking, “This feature feels new, and I’m not sure I can pull it off ,” then you really have to keep your overthinking aside.
You already know everything you need to build this. It’s just a matter of connecting the dots.
Remember the lessons where we built forms (Question Form) for submitting questions or handling inputs with react-hook-form? The core concepts are the same—this is just a new context where you’ll apply those skills.
So, instead of walking you through step by step, let me help you solidify your knowledge by tackling this real-world challenge.
Unlike creating something from scratch (like the question form), this time, you’re working with existing data — a user’s profile.
That means:
Pre-fill the form fields with their current information
You'll reuse the getUser function to fetch the user's profile data and pass it to the ProfileForm component. In app/(root)/profile/edit/page.tsx, it looks like this:
const Page = async () => {
const session = await auth();
if (!session?.user?.id) redirect(ROUTES.SIGN_IN);
const { success, data } = await getUser({ userId: session.user.id });
if (!success) redirect(ROUTES.SIGN_IN);
return (
<>
<h1 className="h1-bold text-dark100_light900">Edit Profile</h1>
<ProfileForm user={data?.user as User} />
</>
);
};
Validate the changes and ensure nothing breaks
You’ll use react-hook-form, Zod, and the necessary ShadCN elements, all while setting default values from the user's profile data passed as props. It's the same process you've used before, just applied to an editable form.
Handle the backend logic to save the updates correctly
You’ll create a server action that receives the updated user data and saves it to the database, complete with validation and error handling
export async function updateUser(
params: UpdateUserParams
): Promise<ActionResponse<{ user: User }>> {
const validationResult = await action({
params,
schema: UpdateUserSchema,
authorize: true,
});
if (validationResult instanceof Error) {
return handleError(validationResult) as ErrorResponse;
}
const { user } = validationResult.session!;
try {
const updatedUser = await User.findByIdAndUpdate(user?.id, params, {
new: true,
});
return {
success: true,
data: { user: JSON.parse(JSON.stringify(updatedUser)) },
};
} catch (error) {
return handleError(error) as ErrorResponse;
}
}
Does this feel like too much? It shouldn’t.
You're not being thrown into the deep end—you're just walking a familiar path... with a slightly different view.
You don’t need to second-guess it. Just open your editor and start connecting the dots.
You've got everything you need.
Complete source code for this lesson is available at