Using React Hook Form, Zod Validation and Server Actions in NextJs 13

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to talk about react hook forms zot validation and also server actions in Nexus 13. we're going to build a form like what you see on the screen here where we can pass in a name and a message we have validation and then once we submit in this case we're hitting our server action which just then returns this parsed safe validated data back to us we're going to use an API endpoint and then we're going to turn that API endpoint or replace that API endpoint with a server action so let's jump right into the code where I can explain what we're doing so I've started a brand new nextgs application by running npx create next app I'm using the app directory and I have also enabled server actions as we're going to use it at the end server actions are still in Alpha version so you'd have to turn this experimental flag on to be able to use them in the beginning we're not going to use it but just so you know this is the setup that I have and I'm also using Telvin CSS other than that I'm just using what comes out of the box when you install next JS with their script now I haven't touched the layout it's what exactly you get out of the box but I have removed the content of the home page and replaced it with these forms that we're going to review together so let's start from our simple form and see what we are doing here we are rendering a form has two inputs one is name and the other one is a message and this is for someone to leave a message or a comment on our site we're going to pretend or mimic that behavior by calling our API endpoints so this form as you can see has a handle submit function attached to the on submit event where we would prevent the default behavior of the form submission get a reference to our form by accessing event.coin Target creating a new form data object out of that form and then passing it to object Dot from entries to get an object where we're going to then call our API endpoint for slash form make a post request and then send that form data object to it get the response back turn it into Json and then set this data as our local state using user state from react and then resetting our form at the end now this Json data is going to then be viewed in this pre-tag that you can see on the right hand side so once I actually go ahead and submit this form with whatever message you'd be able to see this response on the right hand side now I'm not doing much in the API endpoint but just so you know inside the app inside the API folder I have this form endpoint and a route.ts file inside of it and as you can see here I have exported an async function called post these are named methods mapping to http methods I'm getting the data out of the request body this is how you would get the body of your request and then I'm returning your next response Json response passing that same data back to the front end so if you're not doing anything here it would be typically where you talk to your database create a new record in your database or whatever that form is intended to do now going back over here to our simple form as you can see I'm not using any local state um maybe Pro even another step instead of doing it like this using this form data is to use controlled components from react where you're controlling every input with react state so you would have a state for your form or a state for each individual input where you would listen for change on those inputs and then update the estate on these and then do similar things when you are submitting the form but actually reading your local state instead of reading this form data now here we're not validating the data but you can easily use something like the Zod to validate this data before actually you're calling your API endpoints now this is the simplest way of implementing a form in react it's not using control components if you're not using react state so therefore we are not re-rendering this page or our application upon every change that happens on any of these inputs Now The Next Step Up is actually using a library called react hook forms now reactbook forms is a library to implement forms in react it's actually a performant or flexible way to work with forums in react because it's not using react State therefore it is not causing your entire page to re-render on form input changes and it's actually very easy to validate it integrates nicely with schema validation tools such as yup or Zod which we're going to see here you can go to the get started section to understand how you would go about installing and bringing it inside your application so let me just also open this form that we have with react hook forms and I'm going to explain how we're implementing react hook forms and how it is different from the simple form that we just had now from a high level in this component we are rendering a form with the same two inputs the name and the message we had previously and a submit button and also a section to render the data coming back from our API but on top of that we're using this use form hook that we got out of the react hook form library now this Hook is going to give you some helper functions and objects to allow you to hook into your form now the main function you would want to know or work with is the register where it allows you to register different fields into your form State you would call this function and actually spread it over your inputs and now the first argument you need to pass to the register function is the name attribute of your field for example here I have a name field and I have a message field so therefore I'm calling this register function with the name and also the second time with this message this is going to be the name attribute of the field it's just coincidentally the same as the name that I'm using here so for example if if this was an email field I would just pass in email instead but you get the idea now this register function also supports built-in HTML form validations such as required mean Max mean length pattern and max length for example here I'm using the required option and instead of just passing it to True which also works you can pass in a message which is going to be used inside your errors object if this field is not actually provided from the user now before I get to the error object let's also examine what we're doing on the message so here I am calling this function with the message name and I'm saying it's required and I also use the mean length attribute or form validation from HTML and I say the value needs to be 4 and the error message for when it's not actually four characters should be this text now from this hook as you can see up here we get this form State back on the form State we have this errors object which maps to this different inputs that you have so on there is object I have a property which maps to that same name that we pass in here so errors.name and then if this exists it's going to actually have a property of message which maps to this message that we provided here also down here we have the errors object on it there's this message property which again maps to the name that they passed in here and on it if there is any errors is going to be another message property where you could use it to actually show down here so let's go to our application now and if I refresh this is now using the react hook forms so if I go ahead and submit you would see these error messages popping up name is required this is the message that we provided here for when the name is missing and also message is required is this message that they passed in when we were calling this register function okay now if I provide a name that error goes away and if I provide something here that's less than four characters it's going to show this message that says message must have at least four characters okay and if there is no errors it's going to go ahead and submit the form and get the response back from our API now let's actually quickly look at the submission this use form Hook is going to actually also give you a handle submit function as you can see here I'm calling this handle submit function this function takes in a callback the Callback that you can Define gets the data that was submitted by the user this is your form data and then you can do whatever you want to do here in this case I'm just setting the data to this local state without even talking to our API endpoint you could do the same thing you can call your API from here you get the idea this process form function or callback is where you would write the logic of talking to your API or do whatever you need to do once this form is submitted then you would pass in this callback to this handle submit that you get from the use form hook and then pass it to this on submit Handler of your form now the good thing is that if any of these validations are not passing react hook forms is not going to allow you to submit or the user to submit with an unvalid data or form data and it's also going to bring the focus back on the field that has the error as you can see here if I try to submit it brings the focus back on this field now to just use form hook you can provide default values if you want to bring in any default values or pre-populate this inputs with any values you could use this object and pass it to your use form hook and we can also pass in a form validation resolver which we're going to see in the next step to this use form hook before implementing this scheme of validation I just want to mention another feature in react hook forms now as I mentioned it doesn't use react state by default under the hood so therefore when the user is updating these form inputs it doesn't re-render the entire form or the entire page instead it's using refs and a subscription model for you to subscribe to changes of these inputs if you want to and that's through this watch function but before we see this what watch function I just want to show you something here if I comment this rendering back in and open my console as you can see here if I continue let me just make this a bit bigger if I continue typing in here this rendering is not logged in here if this was implemented with react state where you are listening to changes of this input and then updating the state which causes this form to re-render you would see this console log being logged here as many times as the user is actually hitting or on any keystroke now sometimes if you actually do want to listen to our changes or we want our state to be updated with every keystroke we want to listen to the changes of what the user is trying to put inside that input this was email from a previous example so I can use this watch function from use form which is going to then watch this specific input now if I start typing inside of this input it is going to actually re-render the form whereas down here I can still type and it does not cause a re-render so it is very performant in when and how it decides to re-render the form or whether or not you've decided to listen to a specific input changes now that's something I wanted to mention before actually moving on to implementing schema validation so let's go back to our home page where we can comment this out and bring in our form with validation I'm using zot now Zod is a typescript first schema validation tool with a static type inference so it helps you create schemas to validate your format schemas or the shape of your form or data and then it supports typescript which is good and then it also allows you to infer your types from the same schemas that you have created so you don't duplicate types and schemas you can just infer your type from your schema we're going to see this in action in a second so let's just see what we're doing inside of this form let me just refresh so we are now using the react hook form with Zod okay so from a high level we are using that same use form and the same form we are rendering down there the only difference is that to this use form hook now I'm passing in a resolver and I am getting this zot resolver function from this hook form resolvers this is actually a library or an npm package from the react hook form team that implements uh useful resolvers for popular schema validation tools such as Zod or yup so if you go back to the documentation you can just scroll down to this schema validation section where they talk about installing this npm package and get that specific resolver this is an example for using yup but if you actually go to npm and search for that package you can see different examples of actually using Zod here as well so you can get the Zod resolver which is going to help you create your schema with sod and then validate your form using this schema and the sort resolver which is what we are doing exactly here so I'm getting the Zod resolver from this package I'm getting Zod which means that you have to install both packages and then down here I'm defining this form data schema inside of my lib folder so because I want to be using this elsewhere I have defined it in a different file so inside of my lip I have this schema.ts where I'll Define different schemas I've defined this form data schema which is an object that has a name property it's going to be a string I want it to be non-empty and if it is empty I'm going to say the name is required and then a message which is also a string not empty and then a minimum of six characters with a specific message so regular thought stuff that you can use now back inside of our form here we are actually using this schema and a feature that comes from Zod that allows you to infer your types from your schema so instead of having to Define this type again we just infer it from the same schema we created now down here as you can see I'm using the salt resolver passing in this schema we created to use form hook and this is going to validate our form data against this schema and it's going to call or handle submit function only if the form data is actually valid now down here in this process form again I'm getting the data I'm resetting my form this is another function that the use form hook gives back so you can use it to reset your form State and then I'm setting the data into a local state that I'm holding up top here so everything is the same as what we had done so far the only difference is now I'm using Zod to validate and I'm not just depending on HTML form validation that comes from the browser so if going back to the previous one I was using built-in HTML form validation properties in the register functions here I have removed all of those I just register different fields by calling this register function and passing in the name attribute for that specific field but I'm actually using zot defining a schema to validate this form data so similarly if I refresh the page and try to submit this page now ignore this warning is because I have extensions running that set some attribute on my document which is going to throw this error but if I go ahead and submit you can see this is throwing some errors these errors are coming from our schema that we Define together so if we go to the schema this name is required and message is required is coming from there so if I implement this name and a message there's six characters is again what we're getting from here so I can say hello world and then that will go away and once I submit this is going to reset the form and actually set that local state which we're showing in this section so similar to the previous process or step or form it's just that we are now using thought to validate our data now the next step is to actually use server actions so instead of having an API endpoint or having or submit Handler call or API endpoint we want to use server actions now if you're not familiar with server actions I have videos on the channel where I dive a bit deeper into server actions but in short they're just functions that run on the server and you can call them from your server components or your client components they eliminate the need to have the intermediary API layer to perform logic to your backend instead you would Define functions and call them from your client components I would do the same thing that you would have otherwise executed or accomplished inside your API endpoint so let's just open up this form and see what we're doing over here now typically when you want to use server actions you're supposed to pass them to the action prop or form action prop of your form or input elements react is going to then call that function when the form is submitted which under the hood is going to make a post request to the same page that you're on now we're not going to dive deeper into server actions here but we can't use the action prop on the form here because we're actually using react hook forms and the way react hook forms work is with this on submit or handle submit change which means react look forms it's actually listening for this submit on our form it's not using the action prop or it doesn't work with that so we still need to use this on submit event handler and get this handle submit function from react hook forms which is tied into our validation so it's going to get called or executed only if our form passes the validation but inside of this process form function or callback that we created instead of calling our API endpoints similar to what we had done in our simple form so inside of this handle submit what we're doing is calling this API endpoint instead we're calling this add entry function which is a server action I've defined in a separate file we're going to look into in a second and check to see if there was any errors if there is you can show a local error State and if not we're going to set this local data state which we have this user state which shows the data on the right hand side here and reset the form so let's actually look at this ad entry function or server action so inside of my app router I have defined this underscore actions.ts it can be actions.txt naming doesn't matter it's just a naming convention that I use the underscore I usually opt this files out of the routing inside the app router which is good for our actions now inside of our actions we are using this use server directive this is how you are supposed to Define server actions that are only meant to run on the server you can pass them or import them into client components so your client components can call these actions but they have to be defined and run and executed on the server now inside of it I'm using or defining this add entry function which is supposed to get some data this is the same data which is the same inputs that we get from this form data schema so it had it's an object with a name and a message property which are strings we're going to get that and the beauty is that we're not actually trusting our form validation that comes in from use form from client side but actually also revalidating this data inside our backend before doing anything so if you're using that same schema that we created again importing it from the lip we are using the save parse method on sort this is going to parse this data against that schema and it's going to give you an object back it's going to either have the success set to True with some data which is the parse data coming out of that safe parse function or it's going to return an object with an error which is an instance of zoder which you can then call format again we're not diving deeper into Zod here we're just validating the data inside of our backend I'm actually just the returning this object with that same parsed data now this is where you would talk to your database this is where you would do anything that you would have done inside your API endpoint to talk actually posting this to your database revalidating this path or redirecting the user to a different page whatever that you wanted to do inside your API you can just perform here this is running on the server so it's safe to connect to your database for this example I'm not doing anything other than returning the data but the con concept or the pattern would be the same this is a server action we've defined and we are actually importing it inside of this client component as you can see use client I'm importing this add entry action from my actions and inside of this process form callback that I'm passing in to use form hook or to react hook form Library I'm actually using this server action to perform whatever I needed to do using this form so let's just refresh the page and quickly test this out I'm just going to close this up I'm going to hit submit again before we actually submit this we're still validating the form using this use form hook the sort resolver and this schema so the name is required message is required so once I put in the name and a message the errors is going to go out and then once I submit this time it's going to call my server action my server action is going to actually parse this data again this is how you're supposed to do it and then Returns the data if it passes the validation which we are setting it to this local state and then showing it over here that's a wrap for this video folks we talked about reactbook forms which is a library that allows you to implement forms in react in a more performant flexible way it ties in really nicely with your schema validation tools like sort that we used in this example and at the end we also implemented or replaced our API endpoint with a server action which is basically just a function running on the server that you can call it from your client side if you have any questions hit me up in the comments like always and until next one bye
Info
Channel: Hamed Bahram
Views: 15,129
Rating: undefined out of 5
Keywords:
Id: R_Pj593TH_Q
Channel Id: undefined
Length: 25min 54sec (1554 seconds)
Published: Thu Aug 17 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.