Multistep Form Custom Hook With React And TypeScript

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video I'm going to show you how to create this really simple multi-step form in react and there's about a million different ways to create this type of application but I'm going to show you a way that uses custom Hooks and is incredibly flexible so it can be applied to pretty much any project you can think of [Music] welcome back to web dev simplified my name is Kyle and my job is to simplify the web for you so you can start building your dream project sooner and to get started I just have a completely blank page on the left in vs code and on the right I have a final version of our application so as you can see we can enter information inside of here we can click next and if we go back all that information is still there we have a counter in the top tone as how many pages we have and as we enter all this different information we finally get to the very end where you can enter the last bit of information and when we click finish it would do something like say that you're signed up or whatever it is that you want it to do it'll just do whatever you want at the end so it has a full multi-step form functionality you can go backwards you can go forward it also works for like if you have required Fields you're required to fill those out before you can even go to the next step it's got a lot of functionality and it's pretty simple what we're going to do so to get started for this project I'm going to be using react and typescript so I'm going to say npm create Vite and that's going to create me a Veet application and here I just say that I want to install this and now it's going to ask me what my project name is we'll just call it react multi step form just like that and we're going to be using react and I want to use typescript so we'll say react TS now you'll see it puts it inside this folder here I'm just going to move everything out of that folder because we're already in our own folder and now I can run npmi and that's going to install all of my different dependencies and then I can run npm run Dev once that's done to run a basic version of our application and you'll see inside here we have a bunch of different files and I want to get rid of most of them I don't really care about the default CSS or the you know icons that they have inside of here all I want to do is just have a basic index HTML and I want an app here that has essentially nothing at all inside of it we're just going to return the text we'll just do it H1 that says hi there we go so now if I just run npm run Dev and just give it a second it should pop that up you can see if we just click on this link now we're running our application it has the text High super straightforward now before we even go ahead and start writing out anything for your HTML of our application I want to get started with that custom hook so we can come here we can create a new file called use multi step forum.ts because this is going to be a typescript file and we can just export that custom hook which is use multi-step form just like that and inside of this custom hook we're going to pass in just one single parameter and that parameter is going to be an array of all of our different steps so if you look over here we have an address section we have a user details section and we have this account set up and essentially each one is a react component and that react component has all these different inputs and so on in it so all we're going to do is just pass an array of different react components to this function and that's going to be how we render out our steps so inside of here we're going to pass it an array of steps and those steps are going to be react elements and an array of them so this is saying any type of react component for example a form right here that we have we're going to pass an array of those to this hook and this Hook is going to manage all the state for what stepper on making sure we render out that step getting this counter working properly making sure these buttons work properly all of that is going to be handled by this one custom hook so inside here what we need to do is we need to first track what step we're currently on so we can just say cons current step index and this is going to be coming from state so we can say set current step index is equal to using State and by default we're just going to set this to zero because we want to start on the very first step then at the bottom here we can just return that current step index and now currently what we've done is we just said hey we have a step index that starts at zero and we're returning that to be used but obviously we want to have ways to go forward and backwards in our steps we also want to return the current step that's actually pretty easy the current step is just going to be our steps at the current step index and I'm just going to call this step instead of current step so this right now is returning us our current step and if we want to go forward or backwards we're going to need to create some functions so we'll create a next function we'll also create a function called back that allows us to go back then a final function called go to and this go to function is just going to take in an index whoops index which is a number and we're just going to go to that exact index in our step so what we can do is for the go to it's super easy we can just set our current step index to our index just like that this is about as easy as it gets for our go to function and we can return that down here go to so now we have a go to function now would make our next function which is pretty easy again we want to call that Set current step index we want to get the index that we are currently on which we'll just put as a variable of I and all I want to do inside of here is I just want to add one to I so we'll say I plus 1 and we'll return that but if I'm at the very end of my page I actually don't want to add one to this so if my index here is greater than my steps dot length minus 1 that means that I've already at the last step let's make this greater than or equal to this means I'm already at the last step or Beyond in that case I just want to return the current index I don't want to increment it otherwise do increment divide 1 and for our back button we're going to do almost the exact same thing but if our index here is less than or equal to zero then I do not want to subtract one from it because I'm already on the very first step so these are just making sure I don't go out of bounds essentially so now we can have next and back inside of here and right there that's a lot of the logic we need inside of this hook already taken care of we can move forward steps backward steps go to a specific step and we have access to that exact step right now so with that done let's actually go ahead and try to start implementing some of this before we run into the problems with dealing with data so back inside of our app TX here what we can do is we can actually return some information in our case we're going to want to have a div and that div is going to be like this card type of look here with that border around it and then inside of that we're going to have our form which contains all of our information for our you know our first name last name age and so on so inside this main div here let's add a custom style to it because we're going to want to make it look just like what we have over here on the right so the first thing I want to do is I want to change the position to relative the reason for that is that this numbering system up here is going to be absolutely positioned so we need this to be relative we're going to change the background here to be white we're going to also add a border which is just a simple one pixel solid black all of these styles are really basic but that's because the point of this tutorial is not about the CSS it's entirely going to be about the JavaScript and the react so for padding we'll do two REM we'll actually have a margin of one REM whoops a border radius in here to give us some rounded corners and that's just going to be 0.5 REM and then finally I'm going to change the font family so it's not quite so ugly we'll just make it aerial by default so with that done we have all that we need over here you can see we have nothing but we have this rectangle showing up for our actual card container where our form is going to go now the first thing I want to do inside of our form is I actually want to put a div and that div is going to be for handling our current step and our total steps as you can see here we have one out of three that's what this div is going to be for so for our style infor we need to make sure we absolutely position this so we'll say the position is going to be absolute on that we also want to specify the top is 0.5 REM so it's in the top and the right is going to be 0.5 REM so it's also going to be in the right hand corner so this is going to be in the top right hand corner and inside here what we need to do is we need to get our current step and we need to get our total steps so for example this would say step one out of two if we're on the very first out of two steps that's what I want to have written here but we need to obviously use that hook in order to get that information so come in here and we'll Implement that hook we'll just say const is equal to use multi-step form and we need to pass it an array of steps in our case we'll just pass it an empty array for now and we'll come in here and we can say that we're going to be getting our steps but we don't have access to our steps from our form and what you could do is you could say const steps equals the empty array pass in whoops pass in your steps here and then you have access to that steps variable and you don't need to get it from here but this is a little bit annoying in my opinion to do so instead what we're going to do is we're going to make it so that our hook automatically Returns the steps we pass in that just makes working with this kind of stuff a little bit easier so now if I come back you can see we have our steps we can get our current step index and now down here we can just replace these values so this is our current step index plus one because we're zero indexed for arrays we wanted to start with one instead of zero and this is just our steps dot length so for now it's just going to say one out of zero because we are currently in empty array which is obviously something that would never happen this is going to be an array with multiple elements inside of it but if we come in here we put like a div that says one and we'll come in here we'll put another div and this one will say two there we go now we have two elements that are being passed they're just react jsx elements and you can see now we're on page one out of two because we're starting at Step Zero which is our very first step right here now the next thing I want to do is render out the step that we're currently on so I'm going to get that up here from our hook and we're just going to render that out right below so now you can see we're on step one and if we're on the next step for example if I just manually change this here to be an index of one now we're going to be on step number two as soon as I do a refresh as you can see right there but obviously we want this to start at zero and we're going to implement Logic for our buttons which is the very next thing I want to add so let's create a container for our buttons we'll do that right here and we're gonna add some manual styles to this again just really basic Styles we'll put a little bit of margin on the top of one REM to space it out from the actual form we're also going to change the display here whoops display that's going to be flex and the reason we're doing that is so we can just add a gap of 0.5 REM and so we can justify the content on the flex end that's just going to put our buttons on the far right hand side of the container so as you can see it's already added some space for us now let's add in some buttons we'll just say back and we'll say next there we go as you can see we now have those buttons showing up and if we come over here you can see it's very similar to what we have over here but obviously we don't want to show the back button on the very first page and we don't want to show the next button on the very last page so we have a little bit of logic we need to write to make sure we show only the correct buttons so for our back button if we're on the very first step I don't want to show it so one way I could do that is I could say if our current step index whoops current step index is equal to zero that means we're on the very first step so I don't want to show it so if it's not equal to zero then what I'm going to do is I'm going to render out this button like this this is one way to do this and now in the very first step you'll see that that doesn't show up but if we go to the Second Step It would show up but I don't like having to manually write this code inside of my app txx I prefer to just have this logic taken care of for me because I may need to do it in many places so instead I'm going to create a variable called is First Step this variable is going to come from our hook here so is first step and inside of that hook we can just return is first step just like that and that's just going to be if we're on the very first step so if our index is equal to zero then we're going to return that so here if we're not on the first step return the back button and our back button is going to have a simple on click and this on click is just going to use that back function so let's create that back function right here now as you can see we're calling that back function when we click the back button same exact thing here we're going to make this be our next function which we're going to get from our hook next just like that and now when I click next you'll notice it moves me to page two but of course you're seeing there's a little bit of a problem it's going next and then it's going back the reason for this is because by default all buttons are submit buttons so our form is being submitted every time we click a button so for now let's just change the type here of our button to be button and that will prevent our form from being submitted because when you submit a form it's going to automatically refresh your page if you give your form no properties so now when I click next you see we go to the next page and back we go to the previous page so this is working fine and it doesn't matter if I click next multiple times it's not going to actually proceed to the next page because we're already on the very last page now this is going to present some problems though but we're going to tackle those in a little bit the next thing I want to do though for our button is I want to make it so that we're on the last page we're going to be calling or having our text be slightly different so if we are on the last step then I want our text to say finish otherwise I wanted to say next and this is last step we can just get from our hook just like we did for the first step so we'll just put that in there come in here we'll say is last step and that's going to be current step index is equal here to our steps dot length minus one that's going to give us the very last step before on the last step this will be true so now when I go to the last step you can see it says finish instead of next which is exactly what we want now I mentioned we're going to run in some problems by using the type of button here and in order to see what those problems are we need to actually create our different steps so what I'm going to do is I'm just going to create a new file we'll call this one userform.tsx export function user form and this user form is going to be really simple it's just going to return some HTML and this HTML is going to look like this I'm just going to copy this in essentially we have a first name we have a last name and we have an h and the main thing about these is all the fields here are required H has a minimum of one and we're Auto focusing on our very first input and that way when we render that input it'll be the first thing that gets our Focus I'm going to do the exact same thing with an address form whoops dot TSX there we go export function address form inside of here we're just going to return essentially the exact same thing but this time we're going to have address related information again they're all required and the very first one has autofocus lastly we're going to come to our final step which is our account form dot TSX export function account form and we just make sure that we're going to return this information and again it's exactly the same autofocus on the first all the other ones are required so now with those three different forms created what we can do is we can actually use them inside of our multi-step form so in our App instead of just passing along these divs I want to pass along these components so we have a user form we're going to pass along we have an address form that we're going to pass along and then we finally have an account form that we're going to pass along we just want to make sure all of these are getting imported so now if I save you can see we have our address our user form we have our address form and we have our account form but our styles are not quite a hundred percent there so in order to style this properly I'm going to essentially add another component that's going to wrap all of our different components that we have here for our forms and that's just going to be for consistency's sake I'm going to create a new file this one's going to be called the formwrapper.tsx and this is just going to be for those styles so export that form wrapper now this form wrapper is going to take in two different properties we're going to have a title and we're also going to have the children so the title is just this label at the very top here for example user details or address and the children are just going to be everything inside of the form wrappers all the different form elements and what we want to do is we want this to have a form wrapper props as the type and we need to create that type so we'll say form wrapper prompts our title is super simple that's a string but our children is a little bit complex we need to use a type called react node this react node type is a special type in react that allows you to accept any type of children a single child an array of children a string anything that can be used as a react jsx child will be accepted by react node it's just a special react type specifically for this now inside here we need to return all of our information the first thing we're going to have is an H2 element that's going to be where our title goes and then we need to obviously return our children but we're going to wrap them inside of a div for different styling purposes so for our title here let's just give them some really simple Styles we want to have text align that's going to be in the center margin 0 that's just going to remove the margin around it like on the top and we're going to add back in the margin on the bottom so we'll say margin bottom is 2 REM just like that so now we have our title portion done let's do our children and again for this it's going to be super straightforward again the Styles don't really matter I'm just using these so it's not super ugly to look at so we're going to do a display of grid we're going to give a gap here of one REM and 0.5 REM to space out each element from one another we're going to justify the content at the flex start so that's just going to be at the very beginning and then we're going to set up our grid template columns so grid template columns we're going to have two columns the first one is the label so we want to Auto size that and the second one is going to be for our actual input and we're going to use a simple min max for that where by default the smallest size it'll be it's just Auto sized and the largest size it'll be is 400 pixels and that's just so it doesn't become too large of a element for us so now with that out of the way let's just save and we have all the code for our form wrapper done so let's Implement that on our user form here we'll just use that form wrapper pass it a title which says user details and make sure we close that off right here so now if I save you can see our form is now styled correctly by using grid on the bottom and this title is showing up just like we want let's do the exact same thing for our address so I'm just going to paste that in here this is going to say address make sure that we import this and copy that down there now let's do the final thing on our account form this will just say account creation it doesn't really matter get that in there and copy this down so now all three of our forms look 100 like we want them to but obviously we already see the issue with our next and previous button not working correctly based on that type of button that's because when I click next even though all of these user fields are required it's not actually checking these to make sure that the actual valid values are there so instead what I want to do in my app is I want to change the type of our button here for next to be a submit button and that's going to mean that we submit our form every time so now when I click next you're noticing that it's kind of refreshing my page it's not working exactly like I wanted to the reason for that is because we're submitting automatically so what I want to do is I want to actually remove this next right here and instead I want to move that to an on submit Handler for our form we're just going to call a function called on submit I'm going to create that up here function on submit which is going to take in a form event object now the first thing I want to do is I want to prevent the default that's going to prevent the page from doing that automatic refresh thing that I talked about and then the next thing that I want to do is I want to call that next function so we'll just call next like this so now just by doing this one step when I click next you'll notice it tries to submit the form by doing the normal on submit and it's noticing these fields are not filled in properly so it's telling me hey add a name add a last name add an age and now when I click next it's going through the on submit it prevents the default behavior of refreshing the page and it's calling my next function just like it worked before but now we actually have the form checking to make sure everything's correct but you'll notice when I go back and forth obviously none of my state is being saved because we don't have any state information at all in our application yet now to actually handle this data it's going to be fairly straightforward what I can do is I can create a local state variable we're just going to call this data and set data and by default we're going to use some State that's set to an initial data variable just like that's just going to be a variable we create up here it's going to be an object now I'm just going to paste in our initial data because we just have all of our different properties first name last name age Street city state ZIP email password they are all just an empty string to start and we're going to give this a type as well which is going to be form data so let's just create a type form data and we're going to equal that here I'm again going to just copy over the code for this because it's super straightforward everything is a string so we just typed everything to be a string you don't want to see me type this out so let's just copy it over so now we have our U state which is this initial data which is a form data and what we want to do is we want to pass that data down to all of our components so we can just say here data just like that and that's going to allow us to pass down all of the data to each one of these components when we save we're obviously going to have some errors because we're not currently accepting data into any of these components but it'll look something like this in our user form we're going to be taking in a first name a last name and an age and this is going to be our user form props user form props and we're going to have our first name which is a string last name String and an age which is a string as well just like that and now that's going to get rid of the errors for our user form here but we also need a way to update this state because we can pass in all of our information so if we go back here we could say for example the value of our input is going to be first name we could copy that down for all three of these so we have our last name and we have our age last name age and now that's going to put those values in there but we have no way to update them we need some type of method which for example would be like update fields which is going to allow us to update each one of these fields and the way I Envision this update Fields function working is something like this you would say update fields and you would pass it and update for example first name is going to be Kyle this would update the first name to be Kyle or you could add in last name to be cooked and now it'll update the first and last name properly so that's how this is going to work so let's actually Implement that function here we just say function update fields and this update Fields function is going to take in some fields and those fields are going to be the type of form data but we don't want to pass in the full exact form data every time we just want to patch in some partial version of it and luckily in typescript we have a type called partial and if we use the partial type it allows us to essentially pass in a partial version of any type so everything is optional so we only need to pass in you know any of the values it doesn't have to be all of them at once otherwise without that we would need to pass in every single one of these types every single time we call this function so now in this update fields we can set our data and of course we want to get our previous data from the last render and with this what we want to do is we just want to return we take all of the current values and we add in all of the new values we're just overriding all the old information with the new information and now we can pass update Fields here to each one of these functions or each one of these components sorry so there we go we've now passed that into each one of the components and inside here we need to make this update Fields type so we can just come in here and say update fields we know that this is a function that takes in some fields and it's going to return to us nothing void but what is the type of this Fields here well the type of fields is anything between first name last name and age or any combination of them so to make this a little bit easier I'm going to create another type this type is going to be called user data and that's just going to be first name last name age and here I'm going to say that this is going to be the type of user data and so it essentially just combines our two types together it has all of these properties plus this new property and these fields is again just going to be a partial of any of our user data so again the way that this is working is we're saying update Fields when we call it we can pass any information between first name last name age we can pass none of them all of them or any amount of them that's what partial allows us to do and that is going to be our Fields right here so when an on change what we could do is we could get our e value and we could say update Fields we're going to pass in our property here which is first name and that first name is going to be set to e.target.value and now if I save you can see we can now update this first name property but of course it's not actually working as we expect the reason for this is if we go back here this is update Fields so I just spelled this wrong so I should spell that correctly on all of those so now we can update that first name property and it's working just fine if I go next if I actually finish this so let's finish our user form here that way I can actually click the next button I'll just copy this down actually we just need the on change I'm just going to copy that to each one of these and here we want this to be the last name and this one down here is the age so now if I fill out all this information click next and go back you can see our data is being persisted because now we're storing it in state and every single time we render out a component we're passing down the data as well as a way to update that data for each one of our different components so now all we need to do is do the same thing we did for our user form in our address form and our other forms I'm going to kind of copy over this into our address form because it's going to be pretty similar we're going to have a street property we're going to have a city here we're going to have a state and finally we're going to have our ZIP code section and this is going to be our address data just like that and this is our address form props and again our update field is going to work the same we just pass in our age our address data instead so now I'm going to copy this because this is going to be almost again the exact same for all of these this will be our street and here we update our street that should be exactly how this works make sure I spell Street properly and of course we need to make sure we get all these props so Street city state ZIP and update Fields comes from that address form props should have no errors there and now I can just copy this down to each one of our different inputs I just want to make sure that for our city we're updating our city for our state updating our state and for our ZIP we're updating our ZIP and now if I come in here you can see I can enter in information for all of these so next go back it's all still going to be there for all of these different things now finally the account creation very similar I'm again just going to copy this over paste this down we only have two we have our email and our password just like that so here this is going to be our count data and this will say count form props and let's get in our email our password update fields and finally I'll just copy over this information again so we can just paste that down and set a street we're going to have email instead of Street down here password there we go so now hopefully all this information should be fine to fill in let's just do all that real quick email and we click finish and we are not getting any errors so this should be submitting our form also I need to make sure here that this is using our address whoops account form props there we go that'll just fix the type right there so now if we go back to our app here we're calling this submit function whoops this submit function right here every time we click next but we only want to go to the next page when we're on all the pages except for the last so if we are on the last page so if is last step if it's not the last step then let's call next and do nothing else so we'll just return right here otherwise we want to do something for now I'll just say alert of successful whoops successful account creation so now we should only call this alert function whenever we click the Finish button so let's go back to the beginning here when I click next it goes to the next step click next again it's still going to the next step but now we're on the last step so it should skip this and instead do this alert and as you can see it says alert successful account creation and here is where you could do anything like a fetch request to post this data to some type of API whatever it is you need to do that can go up right here also one final thing we should probably do is fix some CSS Styles you'll notice when this is very zoomed out it's way wider than it should be we just need to set the max whoops Max wit to be our Max content and that'll just make it so our container here is never actually wider than the content inside of it which is what we want and that's all it takes to create a multi-step react form if you want to see me attempt this in JavaScript completely live and unscripted that's going to be linked over here as well as another Advanced react project that's written in typescript with that said thank you very much for watching and have a good day
Info
Channel: Web Dev Simplified
Views: 88,745
Rating: undefined out of 5
Keywords: webdevsimplified, multistep form, react typescript, react ts, react js typescript, react js ts, react js project, react js, react typescript project, react project, react multistep form, react ts multistep form, react typescript multistep form
Id: uDCBSnWkuH0
Channel Id: undefined
Length: 28min 22sec (1702 seconds)
Published: Tue Oct 04 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.