React form validation explained - Next.js and Astro

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
let's talk about form validation in your react apps there's a lot of moving parts that you might not think about like validating server side and handling form data objects and validating on the client so you get live feedback while you're filling out a form there are libraries that address some parts of the equation but I want to give you the full stack solution let's jump into an example we're going to build a ticketing site that takes your email the amount of tickets you want and rights to a database on success and we're going to use my dream concert as an example SAA live in Brooklyn if yall haven't heard of this man just go listen to his new album it's absolutely Flawless but we have the event page now we want to add a form that takes all those inputs and submits to a back end of some kind we're going to do this demo using Astro but stick around till the end we're going to talk about nextjs as well in server actions we're also going to use a flexible Library I built for any framework called simple form this lets you use Zod which is a great validation for full stack apps to make sure a form matches the format we expect like numbers strings bullan check boxes whatever you're working with and gives you hooks both on the back end and the front end to validate everything let's take a look at the code I have an astro page right here and we're using a dynamic parameter at the Top If you've used nextjs Pages router you probably know about this we're going to take in the event name and we're going to display our form and event description this is pulling from a simple database I wired this up using cloudflare D1 because I'm fancy but of course you could use whatever SQL you want and here's the schema for a little bit of visibility we have an events table with the name description and ticket price and an event can have multiple tickets so the event ID and the email quantity and a newsletter opt in for the right amount of spam when you sign up for an event cuz what's a ticketing site without a little spam right so let's add a form to this page and we're going to start just with the back end piece use a lowercase form we're going to send off a post request and we're going to have all of our inputs as plain old HTML inputs so the email for example is going to be a label of type email and an input right here which is type email if you didn't know the browser supports an email type so that you get rage Xing and validation without having to write any clients side JavaScript pretty cool we're also going to give it the name email and make sure it's required and for the rest of the inputs I just have a little snippet right here to save us some time we have the quantity and we have our check box to hear more about the next event in your area we head back to our page here and we can see that form appears for us we have the email quantity he about us nice so now in order to submit this we're going to need a button of course so we'll add a button of type submit which is actually the default but we'll add it to be a little explicit and we're going to add the backend code to receive this form so we know it's going to be a post request if you're using Astro you can just check the request object directly so you can say Astro request method and make sure that it is a post request and then you can parse the information out of the form I'm going to use this little diddy right here grab the request post and parse out the form data this is a web standard object that can parses Json or form data in this case and we'll use that object to grab our inputs and console log to make sure we receive everything with all that wired up we can head back to our page we can type in an email that is totally not real please don't spam me and we'll register for the event you can see right here we have our uh log bogus beh holes Dev 3 and the value of the checkbox if you didn't know checkboxes are a little Annoying to work with they don't return true false bullens they actually return the word on or the word off it's weird and that's the reason people reach for thirdparty libraries to parse these kinds of inputs and we're going to do exactly that we're going to install this into our project as simple stack form you can also use the Astro ad command if you want to be fancy this will not only install the dependencies but also give you the peer dependencies and you can see right there it's going to install Zod for us it will also wire up our config to make sure all the types are up to date and when we restart our Dev server we have access to all the simple form apis so to start we're going to model our form now as a validator object we're going to call this ticket form and we'll use the cre create form utility to specify all the inputs we're going to start with email this is going to be uh Zing using Zod and we'll make it an email input to use that email type we alluded to earlier it'll handle that for you we also have a quantity which should be a number it shouldn't be an INT but it would be nice to have a minimum value and a maximum in case we don't want too many tickets in someone's cart lastly We'll add our newsletter Boolean and this will just be Ze Boolean and you might imagine imine what what about all that parsing you mentioned onof being something we have to deal with well using simple form it will convert any onoff values to a bullion for you so you don't have to think about that it'll also parse numbers and make sure of the Min and Max values RX emails on the back end to make sure no malicious request come through all of that is handled and if we want to parse the form request we no longer need the conditional or any of that we can instead say result is equal to Astro locals form this is a middleware function that's available in all of your pages and you can call get data this is going to try and parse out any form data in the request if there isn't any result will just be empty this is going to be like you visit the page for the first time you haven't submitted anything yet but as soon as you do submit a value you'll get a data result with all of the parse values and if the parsing fails you also get some field errors to display some nice styled error banners however you want to do that so now let's wire up those inputs we don't really have to do any work if we don't want to deal with the input I'm going to console log it right now to show what we're working with and you can see it's undefined to start but as soon as we request something from the page we can increase that register our form and now we see our parsed results so the email was valid we get that we get a quantity now parsed to a number and newsletter now parsed to a Boolean don't have to deal with funky types anymore pretty nice and it does give you some nice affordances to keep your in puts in line with your validator you know here we're manually saying this is type email and it has the name email but if we change this to be uh user email for example or username or something like that well we want to make sure this name is updated as well you can of course manage that manually or you can use one of our utilities to spread all of the required props and here we're going to say ticket form. input props doil and this is going to apply apply all of the types you can also see there it detected that it's going to apply the type for us as well so there really is nothing we got to do except add an ID for the label and let's update those other inputs to match the prop spreading if we head back to our UI we noce looks exactly the same it applied the number and checkbox type for us but what about those errors that we mentioned before you know we know what to do when it's successful but what if there's too many tickets in the cart for example how do we show errors that came from the server well you can check the result object for those you can say re and you'll notice it's data if it's successful or field errors if something went wrong for example we might have an issue with the email and this will log out any errors that might have come from the email input it might say it's required it's required and it didn't match the RX whatever set of error messages we might have so we're going to map all of those out and we'll also add a little CSS class to make it look nice now if we head back to our UI and we type in a bad email for example it will give us back an invalid email message pretty simple right so now let's actually persist this stuff in the database we've been working with console logs but we do have a server so we'll say if there is data do a DB insert this is going to prepare a SQL statement and grab out all of the data that's coming off of here we just need a little question mark to make sure of that I also add a little plus sign here this is a way to quickly convert a Boolean to an integer value you because a database only supports integers just a little shortcut to make everything work we're also going to add a check if you did get a ticket so this is going to be another database query you can imagine we join on a user table to actually use authentication but for now we'll just do it in a global way check if any tickets exist for that event and whether you checked out and if there are tickets available or if you did check out a ticket we will render out a nice little success message so we can see down here you're going you have purchased this many tickets for this event check your email for your tickets let's check the UI to make sure all of that stuff works as expected I'll type in my bogus email again increase the quantity and submit that now we see Woo you're going you purchase three tickets check this email for your tickets okay so we wrote an app that would make the 1990s internet proud but uh we have client side JavaScript right we could make this a little bit nicer for example say I type in a bad email and I move on to the next input it shouldn't wait until I submit the form and send off to the server if something is wrong it should give me some instant feedback like whoa whoa whoa you typed in a username instead of an email back up correct your error and then move on for that we're going to use a little pattern that's called reward early punish late let's take that backend validator and use it to make our front end feel Snappy we'll do this using the reward early punish late pattern this is a best prct practice of when to show error states to a user let's say we have a newsletter sign up form user comes in to fill out their email and maybe they type in their username by accident we could wait for you to submit to validate that but if we had a bunch of other inputs be really frustrating to validate that late in the game so maybe we move validation to on input so it's live but that gets pretty noisy we're typing a single character draws your attention to an error State that's too early what if we used on blur instead that way we only check your work when you move on to the next input so we know you're done in other words punish late so what about when you go to correct the error we could also use on blur for that but that means the error lingers even when you've corrected it you have to change Focus to force it which most people wouldn't think to do in this case I'd flip back to on input so you get that feedback right when you correct it in other words reward early so our Puda code looks something like this on blur validate the form and if it's invalid track that it has errored before then on input check if it has errored then we can enter our live validation mode but you don't have to write that code you can run simple form create to generate a form with all that code in your project let's see how that works thank you Mr whiteboard so let's apply what we learned there to our application luckily simple form will code generate all the code we need I'm going to call simple- form create and that going to detect whatever framework you're using if you're in nextjs for example it'll give you a react template we're using preact because it's just react with less client side JavaScript it works the same way so I'm going to say yes plop it in my components folder and we should see a form. TSX appear this includes some niceties to validate individual fields and also track loading States and other things it's provided by this big context object but the part that you're probably wondering about is the actual form and and input value so the form is going to validate every time you try to submit it'll also give you a submit status if you want to show a loading indicator and in the input section we're applying the reward early punish late pattern so you can see on blur we're going to validate that value and on input we're only going to validate if it is dirty or it has errored sometime in the past you also notice this little special check right here to say if it is like a required field and you it empty don't show that error message right away CU it is really frustrating if you're tabbing through a form to see what you want to fill out to lead this trail of required messages as you're working through it so it's kind of a better practice to only show required banners when you hit submit but for any other kind of error like you typed out something and it's invalid go ahead and do that on blur instead so treat that as a little special case for required let's compose those into a client validated form I'm going to create a client side component for this I use the underscore convention so I can collocate inside of the Pages directory if you're using nextjs and app router you would just call this ticket. TSX and put it alongside your page and I'm going to add in a component we'll call it function ticket or probably ticket form so we know what we're talking about and down here we're going to add in our form from the components folder this should Auto Import for us and it'll accept a validator which is our Zod object that we created before so I'm going to leave that blank for now but we're going to grab that out of our server directory and inside of here we're going to add in all of our inputs this is a nice little bit of autocomplete but instead I just want to grab all of the inputs out of here and I also forgot to grab my button so I'll do that as well and you'll notice we get some red squigglies because we need our ticket form validator so I'm going to grab this out of the server code as well this is now going to ship client side so whatever you put in your validation code know that it is now running server and client Zod is totally safe to ship to the client and for simple forms like this makes a lot of sense to use the same validation both places now for the validator pass in the ticket form. validator and for all of these inputs we can actually remove the error messages because if you replace lowercase input with uppercase input this is going to render out those airor messages for us if we click into this you can see down here there's any validation errors in the state we will render it out here and you can also style this yourself I have an error class that I want to add so I'll write that right there we can replace all the other code in here with the same sort of thing lowercase to uppercase upgrading our server logic to client logic and that's pretty much everything we need now we'll head back to our server and we'll import all of those dependencies so ticket form is now coming from the client file and heading down here we can replace our lowercase form with an uppercase form so we're going to grab our ticket form component and we're going to add a client directive if you're using something like react server components you'll put use client at the top of that ticket file or if you're using AST you put the client directive where you use the component and load will make sure it is server rendered as well and I'll add in the little conditional that I accidentally deleted head back up here and we should see going back to the client the exact same form form now hydrated with react or preact in this case so if we fill out a form and we put in a bad value tabbing will immediately give you feedback so we see the invalid email message right away and as soon as we correct the error it will have that message disappear it also reappear if you're typing and you go from good to bad to good again because once you filled something out you probably want live validation to really fix what's going on for the quantity we're also going to see something like that if we put in 12 and needs to be less than or equal to 10 if you want to massage that to a better error message you can totally override it that's just a default that comes from Zod and the same thing if we go to low you can also put negative values on the browser if you're not careful so go ahead and add a little bit of validation there and once everything is filled out it will successfully submit to the server you're going 10 tickets purchased check your email so pretty nice right now we're validating things both client side and server side and all we had to do was move move our server code to a client module and import a couple components that we didn't even write ourselves so as promised I also have a nextjs example for you you can find this on our example repositories with an online playground and you can see we set up a signup form that's a little bit simpler to demo everything so we are using the same create form utility you can use this in any framework you want coming from simple stack form slm module you can also use Zod just as we did in the Astro example and to set up form actions and other things we're going to use the client side validator so I have an example action right here that submits a signup form and you can call this validate form utility that comes straight from simple stack form this takes form data your validator and make sure that all the data looks correct we can see in the parse result it's going to give you data or field errors as you might expect and if there is data we're going to just console log it to make sure that everything is working correctly heading over to sign up we can see we're using reacts use form state in order to take whatever action we have and turn it into something that we can watch this will give us that data when it comes down and also the form action to wire into a form you'll notice some squiggles though that's because we want to generate a form for the first time so we're going to call simple form create inside this nextjs example make sure you have simple stack form installed and you'll get this nice command you can also see we're using it outside of asra so it'll give us a generic rea template and it'll plop it in the components directory you can see this generates a simple form the same way it did in Astro the only difference is the submit Handler instead of using Astro internals it's now a generic bucket for you to put whatever logic you want like fetching from a Json API if you're using nextjs Pages router or remix or you can add in a server action call if you're using something more modern we'll do that inside of here remove that to-do and instead just call an action with the form data and this action can come down as a prop or you can just import it in line I'm going to be a little bit more proper and add an action here it's pretty simple type signature takes form data does some work on the server and we'll use reacts use form state in order to track the result if we head back to our signup form we can go ahead and pass this prop you can see we're passing down that form action that we demoed earlier and we're going to use the same uppercase form and uppercase input convention now we can start up our Dev server to see that server action in action heading over here it's a super simple page actually has full stack forms and we can type in our name the opin and if we hit submit we should see a console log on the other side there we go success you have submitted the form we're using use form state to track that we can also see our parts data right here username and optin converted to a Boolean all right I hope there's some takeaways for form validation in your apps even if you don't use simple form the reward early punish late pattern it's a really great way to do validation if you're using final form or react hook form or tanack form which is a new one they all offer Utilities in order to make that pattern happen and if you want to check out simple form you can head over to simple- st.dev there's a whole Suite of tools over there including form management all right so if you like this video drop a like subscribe for regular content I love working with react and Astro so if you like that kind of content I'll see on the Channel all right see you in the next video
Info
Channel: Ben Holmes
Views: 6,332
Rating: undefined out of 5
Keywords:
Id: DwEkvie79xI
Channel Id: undefined
Length: 20min 1sec (1201 seconds)
Published: Fri Jan 19 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.