Create and Utilize a User Model with Prisma in Remix

Ian Jones
InstructorIan Jones
Share this video with your friends

Social Share Links

Send Tweet

In lesson 08, Deploy a Remix Application, we said that the app was MVP status. This isn’t quite true for many applications. You will inevitably need users on your site to make it useful for your customers (or even for yourself).

To get started adding users, you will update Prisma with a user model and associate it to Posts. From there you’ll update your posts to display user information. You’ll see how to migrate a Prisma schema in PlanetScale as you deploy these changes.

One nice tid bit you will pick up along the way is a TypeScript 4.5 feature, Awaited. Awaited will unwrap a promise type for you so that you don’t have to do it yourself which is a big relief.

Instructor: [0:00] The next part in your application building journey is to add authentication. Authentication is a big piece of almost every application you see on the web today.

[0:12] I want to take you through form authentication where a user signs up with a username and password. The first step is to add a user model to Prisma into your database. A user row will be created whenever someone signs up for an account.

[0:28] Go ahead and create a new PlanetScale branch called User.

[0:37] In another tab, you can connect the branch you just created. With Pscale connect, remake social, user passing in the port. Now, you can create a Git branch. Make sure to pull master before you create a new branch to get the latest changes.

[0:56] It's a good idea to always branch both your database and your code. This allows you to keep track of changes over time, and document step-by-step how your code changes.

[1:07] It is time to update your Prisma schema. As you can see, you have an ID created at and updated fields, all of which are managed by Prisma. There's a name that's optional and email that's required, and this is unique.

[1:24] This is what a user will use to log in to their account. There's a hashed password and a roll of default of user. Users will have many posts. This connection is important.

[1:38] Eventually, users will be able to follow each other to view one another's posts. You have to be able to associate post with a user. Prisma is telling you that this is an error because it knows that the post doesn't have any reference to the user model yet.

[1:55] Let's add the reference. Now, the post has an author ID that points to a user row. When you reference a post, you will be able to query the author along with the post and access the author via post.author.

[2:11] Let's go push our changes up to PlanetScale. Like always, run npx prisma db push.

[2:22] Now, you can add users to the database, open up Prisma Studio, and you can create a user with a post.

[2:36] There you go. Now, you have a user. Obviously, this password isn't hashed. When you add the signup process, you will hash the password before you create the user. Over in the post table, you can add a post and reference it to the user.

[2:52] All ready. Let's head back to the terminal and restart the development server. You can see here, you have Ian's first post, but none of the user information is being displayed. Let's add the author name to this post. Add the author name to the props and you can display the author named conditionally in a paragraph tag.

[3:29] Next, you can add the author name prop to your types as an optional string. It's time to add the author to our getPost call in post.server. It looks like Create Post is complaining because the author ID is required now.

[3:51] Add an author ID to fix the issue.

[3:59] For the getPost call, you can add include users. You don't want to include the hashed password to the user. You can pass a Select-Object and grab the email and ID.

[4:13] For Prisma, include is additive. It will return all attributes on the post. Then any attributes you selected on the user. Select is the opposite. You have to explicitly select all the attributes you want Prisma to return.

[4:31] Head over to the Index Route. Now you can add post.author.email as the author name prop to the post component. TypeScript will complain about this, but when you head over to the browser, you can see the email field being displayed under the post.

[4:48] It's time to make TypeScript happy. Create Post needs an author ID. You can pass a non-existent ID for now and we'll fix it in the future. To fix the loader data type, you can use the return type from getPost to accomplish this.

[5:08] You will notice that the post type that is returned is wrapped in a Prisma Promise. You can use this awaited TypeScript utility type to access the type that is being wrapped by the Promise. I had to Google around a bit to find the solution.

[5:25] Luckily, Awaited is a new-utility type added in TypeScript 4.5 that solves this exact problem. Previously, you had to add a custom type to your project to unwrap a premise type.

[5:40] The other benefit of this approach is that now you can change the get_post() function without worrying about TypeScript being upset in the future. You are all finished with the code changes.

[5:53] I opened up a deploy request for the user branch on PlanetScale and ran into some errors. There's an error merging the post table. When you add a column to a table, you have to give a row, a default value.

[6:08] To resolve this error, you can merge this deploy request and make the author ID on the Post Table, default to null. Back to the schema file, you can add a question mark to the author and author ID attributes on the post.

[6:24] With these changes in place, push them up to PlanetScale with npx prisma db push. Now on PlanetScale, you can open up another deploy request and make the author ID default to null.

[6:47] To review, you added the user model. This model has basic user information like name and email. A user has many posts on the post model. You make the author optional. Next, you updated the get_post() function.

[7:05] You pass then Includes-block to add the author email address and ID to the post. Then, down in the post component, you pass the author name.

[7:17] Inside of the index route, you pass the author email to the author name prop. Finally, you fixed the TypeScript error by using some of TypeScripts utility types like return type and awaited.