Reputation: 1
Versions: Next.js 14.1 React 18
I am creating a profile section where a user can update their profile (username, name, and profile_photo). Below, I created a component that has a form (using shadcn) to get the user's details.
I get a TypeError on the User model when running the updateUser action on this component: TypeError on mongoose model
components > forms > PersonalInfo.tsx
"use client"
import * as z from 'zod'
import { zodResolver } from '@hookform/resolvers/zod'
import { UserValidation } from '@/lib/validations/user'
import { useForm } from 'react-hook-form'
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '../ui/form'
import { Input } from '../ui/input'
import Image from 'next/image'
import { Button } from '../ui/button'
import { updateUser } from '@/lib/actions/user.actions'
import { usePathname } from 'next/navigation'
interface Props {
user: {
id: string,
objectId: string,
username: string,
name: string,
image: string,
}
}
const PersonalInfo = ({ user }: Props) => {
const path = usePathname();
const form = useForm<z.infer<typeof UserValidation>>({
resolver: zodResolver(UserValidation),
defaultValues: {
username: user.username || ',',
name: user.name || '',
profile_photo: user.image || '',
}
});
const onSubmit = async(values: z.infer<typeof UserValidation>) => {
await updateUser({
userId: user.id,
username: values.username,
name: values.name,
image: '',
path: path,
})
}
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
>
<FormField
control={form.control}
name='username'
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input
type='text'
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='name'
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input
type='text'
placeholder='name...'
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='profile_photo'
render={({ field }) => (
<FormItem>
<FormLabel>
<Image
src={field.value}
alt='profile_photo'
width={80}
height={80}
priority
/>
</FormLabel>
<FormControl>
<Input
type='file'
accept='image/*'
placeholder='Upload a photo'
/>
</FormControl>
</FormItem>
)}
/>
<Button type='submit'>Update Profile</Button>
</form>
</Form>
)
}
export default PersonalInfo
Note: I intentionally removed the logic for updating images to shorten the code for this question
I then import this form component to my main profile page:
app > (root) > profile > page.tsx
import { profileTabs } from '@/app/constants'
import PersonalInfo from '@/components/forms/PersonalInfo'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { fetchUser } from '@/lib/actions/user.actions'
import { currentUser } from '@clerk/nextjs'
import { redirect } from 'next/navigation'
import React from 'react'
const page = async () => {
const user = await currentUser();
if(!user) redirect('/sign-in');
const userInfo = await fetchUser(user.id);
const userData = {
id: user?.id,
objectId: userInfo?._id,
username: user?.username || userInfo?.username,
name: userInfo?.name,
image: user?.imageUrl || userInfo?.image
}
return (
<div className='page-container'>
<Tabs defaultValue='personal-info' className='w-full'>
<TabsList className='flex flex-1 items-center'>
{profileTabs.map((tab) => (
<TabsTrigger key={tab.value} value={tab.value}>{tab.label}</TabsTrigger>
))}
</TabsList>
<TabsContent value='personal-info' className='flex items-center justify-center'>
<PersonalInfo user={userData} />
</TabsContent>
<TabsContent value='saved'>
<p>SAVED</p>
</TabsContent>
</Tabs>
</div>
)
}
export default page
As you can see above, the fetchUser action works, which gets the details of the current user and pre-fills the form if the data is available (if the user has an existing username, name, and image).
However, when I add the updateUser action inside the PersonalInfo.tsx I get the TypeError.
For more context, here is my model definition:
lib > models > user.model.ts
import mongoose from "mongoose";
const userSchema = new mongoose.Schema({
id: { type: String, required: true },
username: { type: String, required: true, unique: true },
name: { type: String },
image: String,
createdAt: { type: Date, default: Date.now },
savedRecipes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Recipe'
}
],
collections: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Collection'
}
],
isContributor: { type: Boolean, default: false },
isAdmin: { type: Boolean, default: false },
onboarded: { type: Boolean, default: false }
});
const User = mongoose.models.User || mongoose.model('User', userSchema);
export default User;
What could possibly be causing this error on my Mongoose User model?
Upvotes: 0
Views: 231
Reputation: 1
I had the same error and finally found the solution: Refer to NextJS mongoose schema "Cannot read properties of undefined"
Change user.model.ts
const User = mongoose.models?.User || mongoose.model('User', UserSchema)
Upvotes: 0