Building a Google Forms Clone with React Native: Form Validation with Zod

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so we're live what's up not just developers welcome back to a new tutorial today is Friday and today we're gonna build a clone of Google forms well we all know that Google forms has this reputation now of uh closing projects with the latest one being Google domains and before they decide to close Google forms let's go ahead and learn how we can do a Google forms mobile applications ourselves using react native at the core of this tutorial we're gonna actually learn a much uh wider topic when it comes to managing complex multi-step forms in react native this kind of use cases are present in almost any applications that you're building and without the right tools it becomes really challenging to manage this multi-step forms in this tutorial however I'm gonna show you a pretty fun way of managing these complex forms by using variety Technologies and then we're going to have a our form management system is going to be very simple and we're going to manage it with the next tools for this project we're going to use react native paper for the UI elements for the forms like text inputs radio buttons uh check boxes and so on then we're going to manage them logic and the validation of the form using react hook form and powered by Zod we're gonna validate all the fields that we have in our form using um yeah this powerful typescript validator called Zod we're going to do that just by defining the schema basically how should our data look and after that Zod will validate it we'll send the errors to wrecked hook form and we're going to see them on display using react native paper everything is going to be done in the context of an X publication we're going to start from scratch but I um I think that a lot of you will watch this tutorial in order to integrate this complex form Management in your own project so this is going to be um compatible with both x-publication and react native application for this specific one we're going to use the export router to manage the navigation between screens and also typescript so in the end what we're gonna have is we're gonna have a real example um check out form where we have multiple steps in the first one we're going to collect like personal information then maybe the delivery information and lastly the payment information so let's put all of this together in an application that looks like Google forms but is much more useful for mobile applications for yourself this tutorial is going to be useful not only for checkout forms it you can learn a lot from here and apply the same knowledge the same system to other use cases where you have this multi-step forms like user registration feedback and service service a booking form which you might book some accommodation or something else a job application or even onboarding so there's the plan for today if you are ready grab us yourself a cup of coffee and let's jump into it [Applause] foreign who is watching this life how are you doing guys are you exciting for today um and I think for everyone else while you're saying hi and let me know where are you joining us from today um while learning that I'm gonna get started because we have quite a bit of things to do today to to create this application so let's go ahead and start by initializing an empty project using react hook form not rack hook form using Expo and also react Expo router so first of all let me go to my project and when you are in the folder where you keep your projects let's go ahead and run npx create Expo up let's make sure to put at latest in order to take the latest version of createx publication then let's provide the name of our application Google forms and let's provide them a template that is going to use to start and we're gonna use the with router this will start from a template that already has router with router did they oh it's um with Dash router like this this template will come pre-installed with the router and set up in order for us to start clean and have this navigation system already in place hello Daniel from Amsterdam how are you doing Amadeo hi hello so um yeah let's see our application installed while we are waiting for npm to install our dependencies this is a great moment to pause the video minimize it and hit the like button and also make sure to subscribe to the channel because from our statistics let me bring that up not this one where is it I always lose it oh here it is from our analytics we see that only one percent of you who are watching this video are subscribed to the channel which is kind of insane so guys please if you don't mind hit the Subscribe button and let's move on with our tutorial this is our Elite group of one percent Club people who are subscribed to the channel let's go and as you can see just doing that actually worked in our project is ready let's go ahead and open it in Visual Studio code um not like this but code and there we have Google forums here we have it I can close that terminal and let's go ahead and zoom in a bit for everyone to see here we have it come on oh there is a small problem open projects YouTube Google forums and Google forms let's open oh boy I I dragged and dropped the icon over folders here and now I don't know how to open it but we're gonna get there what we can do now is let's run our application oh actually it's here folders so I'm just gonna drag it all right everything is back to normal so now here is our empty Expo project with export router let's go ahead and do npm start to start by development server and right away run it on emulator if you have emulators installed go ahead and press I to run it on iOS or a to run it on Android or if you don't have them installed that's not a problem the easiest way to run this application is to download the Expo go application from Apple Market or play store and then simply scan views QR code and you're going to have application running on your physical device so with that you don't have to mess with Android studio xcode and so on so let's wait for replication to load and render here I need some air coffee time yes let's go all right so now we have like the application running and what we see is a very uh the welcome screen that we get from Expo router in fact we see this screen because we don't have any screens in our application yet and by simply pressing on this button on our device uh we will see that it automatically creates this up directory in our project in Expo router this is where all our screens will will be defined and with by simply creating files in this app directory we're gonna create separate screen in our application so initially we have a app index.js and this is the home screen and a bit later we're gonna add more screens for our multi-step form what I want to do is I want to actually work with typescript and as I see the file is the index.js let's go ahead and simply transform from JS to TSX and if you stop the server and run it again Expo will automatically see that we are that we want to use typescript in our application and we'll ask if we want to install typescript and the dependencies so let's press yes and this will go ahead and install typescript in our package.json and we're going to be able to use typescript in our application can I use Expo on my phone yes you can run Expo applications that you're doing in development using Expo go by downloading it from stores it's available both for Android and iOS so now we can press I to rerun it on the iOS device maybe R to reload and here we see our application running with typescript all right perfect so uh what's next let me go ahead and commit everything before we move to the next step this is the first commit the initialization okay so moving forward [Music] um the way we are going to manage our multi-step form is we're going to create a separate stack navigator for it a separate group of screens that are going to be managed as one single group for that let's go ahead and create a new folder inside our application called checkout in the checkout what we have to do here is first of all provide the home screen of our checkout basically the first route of the checkout that first route is going to be called index TSX and here let's simply export default the first route of our multi-step if we look at our forms here the first route is going to be the one responsible for profile for the personal details like name email and so on so let's call this function this component personal details is going to be a function that simply returns at this moment let's simply return a maybe a view and a text saying personal details we need to make sure to import View and text from react native and text as well from here and how can we see this page well in a moment we're gonna look how we can navigate from one page to another using links but um the way export router is working is it's working based on on URLs very similar to how we navigate on the web so it's going to be easier to Showcase this navigation system on a web browser and let's go ahead in our development tools and press W to open it on web so if I'm gonna open it on web it actually opened it here and now basically the way we navigate here um to which page we navigate here is going to map be mapped to the screen that we defined in our application so because we don't have anything that basically means this is the home screen the the root screen and this screen is our index.js with hello world but if I'm gonna do slash checkout we're gonna see that here we see personal details which means that that if it automatically created this route that whenever we go to a slash checkout which comes from our nameover folder it will render the home screen of a checkout with personal details let's in the same way let's uh maybe I can do a style font size 30 so we can see it better yes maybe I can do it like this for a moment now let's go ahead and Define them the screens for them other steps that we're gonna have the second step is going to be deliver information so let's copy paste this index from the checkout folder and instead of index copy let's call it delivery yeah Lee very and this delivery let's call the component delivery details and here delivery let's do the same once again by coping with delivery and renaming it to the last step is payment payment information payment so the component is going to be payment details and here as well payment Now by going to the checkout we see the personal details because that's our index.tsx if we go to checkout then slash the name of our file for example delivery slash delivery then we're gonna see that the screen with delivery details and if we go to the payment we're gonna see payment details so now with this set of files all the tabs in our form they will be handled as a separate screen and it was really easy to set it object by just by simply creating files in our checkout folder The Next Step may be um yeah the next step let's go ahead and add the navigation between every screen so starting from the home screen in the hello world we will most probably have a link here that will say hey navigate to the checkout to navigate in Expo router we are using the link component link from Expo router and I'm going to add them let me actually re reuse this text field because it has some Styles I'm going to say change the text to check out and instead of a text let's turn it into a link the link expects an href with the location of web page that we want to redirect to so for the checkout we want to go to that slash checkout and now if I'm gonna press on this checkout I'm gonna be redirected to the personal Details page we cannot see anything because it's at the top there but in a moment we're gonna fix it um so now we can navigate from the home screen to the checkout and if I refresh I can go back here and go to the checkout or okay yeah now as we can see um the text personal details is under the Notch and here we have a couple of options I were to use a safe area context here to render the texts um below the notch in order not to render it under the notch or what uh we're actually gonna skip this step and go to the next step right away because it will automatically fix it for us the next step is going to be to specify what kind of navigation container is this checkout because at the moment basically these payments and delivery they are still part of our root Navigator to define the checkout as a separate navigation and in this case a stack to Define it as a stack Navigator where we will be able to move back and forth between screens what we can do is we can create them underscore layout file layout dot TSX the name of a file is is important it should be underscore layout because this layout file is going to determine um is going to to wrap all our screens inside this directory in this case delivery index and payment so here let's export default function and let's say this is going to be check out stack but check out stack and let's return what we can return via stack component that is imported from export router and simply returning this stack here come on now if I'm gonna go to the checkout I see the header with the title index and if I'm gonna navigate to the next page for example in this delivery if I'm gonna have a link here next with href is what what's the URL of the next page it's slash checkout slash this is actually in delivery so after delivery we have payment let's make sure to import here the link and inside index we want to navigate as next to check out slash delivery because this is the second screen so now if I go to the checkout and if I press next here I go to the delivery and automatically can go back through the navigation there here I can go next to the payments and back and back and we are on there first screen of our checkout form now you might think how can we adjust the titles of these Pages because right now they are not capitalized the first one says index here to do that instead of letting Expo router manage all the screens we can hook into them by basically specifying stack dot screen and if we give a name the same name as our file for example index from here when we are targeting that screen and we can provide options for the screen and options can be title personal information now we should close it and as you can see the title of the first screen is already personal information if we do the same for them delivery let's say delivery information and if we do the same for payment now if I go to checkout I see personal information next is deliver information next it's payment information maybe info I don't know it depends on on you mm-hmm all right all right all right how can we make the checkout the initial page of application to me okay this is a bit of topic but if you want to make check out the initial page of the initial page of your application inside index.ts instead of exporting a separate file what we can comment out everything here and we can simply say export basically let's first import uh check out from dot checkout and let's do export default checkout hope it should work yes we see the checkout here but it's not including the layout if I go next yeah in this way this personal details is the first one the second one and so on I'm Gonna Leave it how it was but that's one way to do it and our way is to redirect so basically whenever you get here just return um redirect and that's another option let me actually show you for example here instead of returning you can Define them home screen and instead of returning jsx you can return a basically redirect from Expo router and we're gonna redirect to slash checkout and in this situation if you navigate to home screen you are actually going to be redirected to the checkout and I think this is better I think I'm gonna leave it like this in order to have them the checkout always has the home screen another question is this expert routers table yes it is stable you can use it in production does it cover I want a drawer inside a bottom navigation by default it exports only a couple of Navigators the in the layout we see the stack it also has the tabs but you can actually integrate it with any kind of Navigators from rack navigation basically so you can wrap a drawer and we actually covered that in a tutorial I cannot remember exactly which tutorial was that but we have it somewhere on YouTube with drawer and so on okay we went a bit off topic let's come back to our Google Pages application um while we are still here at this tank as you can see we stack and options it looks very similar to Rack navigation if you have experience with rack navigation basically you do because I hope you do because rack navigation has been there the default navigation library for react native applications and in fact export router is using react navigation behind the scenes and that's why we can adjust all web configuration of our screens using options and other parameters from react navigation for example we can use screen options here to apply some options to all of the screens in this tank and what we can do here is for example we can add a content style that will be applied to all the pages inside this one so for example if I'm gonna add padding 15 on this level you see we we get the padding here but not only on this page on all the pages from v-stack the same we can provide um background color back ground color wave I've actually installed the color from from Google forms no that's another one that's another one it's this one yes and also a flex one in order to make sure that the page is takes the whole screen and now yeah it looks better also with the screen options what you can do is you can also adjust the header Style and this is the style of our header bar and we can provide a background color of that purple and it will look much more much closer to how Google forms works but in this case we have to make a title white so let's do header title Style color let's do maybe the color of the background yes and if I press next it works but now we're back back arrows they have um the blue coloring and it doesn't look really well the color of that is used here for the back icon and the back text is actually the tint uh header tint color and we can specify this one so if I go next yes now it's personal info maybe for the title We Can Do It full white to be a bit more distinguished yeah let's do it like this hey priyank thank you very much for the donation I appreciate it uh okay so now our our header looks really nice but another thing that I see here sorry is them um the numbers from the status bar and the icons like them activity bar here at the top we remain black and it doesn't look very well on a dark background like this purple we can adjust them using the status bar from Expo status bar and we have to put it side by side with our stack for that reason I'm gonna wrap everything in an empty fragment and after the stack or maybe even before I will do status bar and the style is going to be light and now the color of the status bar became White and it looks much better on them blue on the purple background okay so we have covered a lot we have we basically implemented them the pages that we're gonna need in the next tab for this multi-step form and yeah let me check if we need anything else navigation between screens is implemented what else yes we are done here with the structure of our navigation the next step is going to be to start working on our form designs so before we do that let's go ahead and do git add git commit um checkout form project structure and yes let's move on okay so for them for the user interface to the forms what we can do is we can basically Implement them ourselves using text inputs from react native that's one option or another option that I thought would be really great for this tutorial is using a UI library that contains pre-made components like text inputs radio buttons and so on the library that we're gonna use is called react native paper let's open the documentation up and let's go ahead to the docs so from the docs let's get started and we're gonna start by installing the library in our application so let's open up the terminal npm install uh rack native paper let's check if we need anything else we also need the safe area context but our application already has it uh if we look in the package we will see a safe area context yes we have it and we don't need to install pods because we are using Expo Vector icons we already have it and yeah that's it in the usage we see that we have to wrap our whole application in the paper provider um how do we do that well in applications that before Expo router the place where we we're setting these Global providers was usually app.js in this case we do not have this app.js file that basically wraps all our screens inside our screens are all individual but the thing is that we can use them root layout file but we have to create layout.ts X and because this root layout will encapsulate all other screens in our application we can use it as a place where to set up our um Global providers so let's do export default function root layout for the right layout we either have to return some kind of Navigator like a stack Navigator or a tabs Navigator but if we don't want to if we want to want to Simply keep what's already there we can use the slot component from Expo router and with this we are back to normal and if I yeah basically with this we are back to normal now if we encapsulate this slot with providers that means that we all the screens that will render will be rendered in our application will be wrapped by that by that provider so let's import them react Nate paper provider or how is it called paper Provider from react native paper and let's wrap our slot with our paper provider put the slot inside and close this provider now let's go on a page like checkout index and try to use a component from that from Rec native paper to see if everything is working so I'm gonna import a simple button from react native paper make sure to import it from here and let's do it after our next button let's create a button here that will say next as well and this button has no corresponding yeah all right so we'll receive a button here uh on the screen it's a text button because there's a default mode but if we change it to which mode Let's see what modes the buttons have button the mode can be contained so if we select contained that um full weave button that is displayed here and with the paper provider what actually happening is we have paper providing provider is supplying the theme variables for all our elements so if we let's see how we can adjust the theme there for example with customization we have to import the MD free light theme and use it like this let's import the default theme that's already there let's define our custom theme as everything we're going to take all the properties from the light theme from Rec native paper and in a moment we're gonna see how we can change some of them but now we should make sure to provide this as a theme to our rec paper provider and with this now you can change for example the roundness is it like this yes if you change the roundness you're gonna see that all the buttons all the inputs and all other components that use round borders it's going to decrease the roundness so if you go to zero that's gonna basically be everything is going to be square for us I think one is okay just slightly maybe two one yeah another thing that you can customize here are colors for example like primary and secondary but I'm gonna leave them as they are because the default ones are purple so it works for our application pretty well hey Samir Amir thank you very much for the donation thank you uh John is asking if I'm gonna add the authentication to this project no we we I don't think we're gonna add authentication to this project but we have covered uh protected routes in our projects um which one in the latest one in the Twitter I think check it out oh so uh we have next year and yeah let's finish this next button with the actual logic of navigating to the next page so we saw one way to navigate to an hour Pages using this link component that we have here with next but if we want to programmatically navigate to another page when we press on some buttons for example here if I'm gonna do on press let's do next page let's Center this on press next page if I'm gonna press I see the console warm that I have here so if we want to programmatically navigate through the screens what we can do is we can directly use them router from export router using this hook use a router imported from Expo router now inside the next page we can do router.push and here we can provide the URL of a new screen for example checkout slash delivery now I can remove this link we don't need it anymore and if I press on the next button I'm redirected to the next page or you can copy paste the same button in vam the next page is our delivery so let's replace this link with the next button we're gonna have to import this next page function and use router in the delivery Details page as well make sure to import export router and button but button not from react native but react native paper rack native come on paper uh so from personal details we go here from delivery info we go next and yeah in the delivery details when pressing next we should go to the Slash payment slash payment it's next we are on the payment details so let's go in the payment details and here we're also going to have a button but this is our last screen so this button probably is going to say submit them function the function will do some kind of submit logic here we're going to talk about that a bit later and we need the router equal use router and let's make sure to import router and also import the button from Rec native paper so when we press next page on the payment details after submitting and validating an error thing probably we should go back to the home page and in the home page I'm gonna actually comment out the redirect because it's gonna loop around so let's see the whole thing in action let's reload from the home page we can go to the checkout from the checkout if we press next we go to the delivery details here next we go to the payment details here submit and we are back to personal yeah not to the checkout but where wait a second in the payment it should go to home screen the router I think in that case why is it going here in the payment let's try a link with her href also home and from payments if I'm gonna go home white redirects here what's happening on the web let's check so if I go to home screen I can go to checkout next and here if I'm gonna go submit I'm back to personal info that is very weird but let's think about it a bit later let's add it to do why it's not navigating home this is like home home actually this one will navigate back so now you see from payments if we press submit I'm going back all right yeah weird but at least we have some basic navigation between the screens and when we press submit we're back to the first to the first screen all right so uh I think we are ready to do git add maybe one dot is in this directory so if you do one dot it's gonna stay there basically or even go at the beginning yeah like this I might understand why because we might get them this stack not the root stack but this one why don't it doesn't it work what if I use the stack here check out next next submit no yeah weird let me editing the notes for the end okay so now let's go ahead and start working on actually the design of our form and here the first one is going to be our personal information on the personal information page we're gonna have two inputs one for the name and one for the email and also we're gonna have like these kind of cards that contain the information I'm not gonna keep very close to this design because I believe we can do better for example I don't see the reason why we have separate cards for separate inputs and for that reason I'm gonna try to group them in the same card to use the space on the screen a bit more efficiently so let's go ahead and open up our index.ts because this is where we will handle the personal details of the information of the user so this form what we need is um is a text input so let's go in the components um maybe before we get into the uh to the text input we're going to look at the card a card is a component that helps us render basically cards with maybe even background title and content so let's go ahead and start using it what we need is the card with maybe a card title and a card content so from Rec native paper let's go ahead and import the card and instead of these personal details We're not gonna need it it's gonna be a car title let's render the card and the card requires a for example give me give me Style so if I go to the card title in the properties title style can be oh title variant I meant it can be title large for example so title variant it's going to be heading large or medium let's go to checkout personal information maybe not even headline but title don't need it that big title large okay that's better so that's our card title and if we're going to use the component card dot content we can provide the content details here so here we can have a text saying hello and we see the text as the content of this card to add some spacing between the card itself and the button I'm gonna simply use the style gap on the parent component and provide a gap of 15 pixels now all the components here will have a gap of 15 pixels between them that's something new in react native what else what else yeah I think let's go ahead in the card content and here is where we will use text inputs let's go to Rack native paper and look for a text input text input is here let's basically import the text input and use it there first text input from react native paper and inside our card content let's render the text input with uh for example you can provide a placeholder name you can also provide a label for example name and this label when you're gonna start writing it's going to be displayed at the top I think this is very nice user interface where you still see the label after you write something so yep that's the label and we can add another one for via email I think for the email the placeholder can be something like like an example nice and let's also add this the same gap for our content container so here if I add Style and we do a gap of 10. it's gonna add this space between them the text inputs themselves um yeah I think that that looks good another thing that we can do is we might want to adjust the background color of a text input so by providing a style here background color white and here as well it's gonna be white but hmm If instead of hard coding colors If instead of this we are going to use them from the theme provider that we Define here paper provider with a film in that case it's going to be very easy for us to make this application light and dark mode so to do that from react native paper we can take the with theme hook and we can get the theme using the weave theme hook use fim now instead of this white we can use film dot colors dot maybe background I'm not sure what background is actually used by the card you know because I want to match the background of a card with a background of my text input so maybe I'm gonna add a style with a background color to the card as well and now they are actually matching second input okay now it looks something like this but let me change my left with your coding now I have a coding YouTube channel that's so cool go subscribe to that develop with Mr shoya what are you doing on the YouTube hmm so we have inputs do we need anything else so we have a name we have email and yeah I think we are good on this uh on this page and we can press next to go to the delivery details let's go ahead and do the same kind of structure with a card with text inputs on our delivery page so what we're gonna need from Rec native paper let's try to do it again in order to make sure that we know how to use this react native paper components so starting with a card instead of deliver details let's go ahead and render the card where we will have a card Dot card dot title where the title will be delivery address and the title variant what did we have here title large then what we're going to have we're gonna have a card dot content with some text inputs imported from not react native but react native paper so the label of the first one what information we will need there for the delivery information maybe City what else um let's say postal code let's go with an address and maybe some yeah in a moment um let's go ahead let's style them a bit in order to match our previous page for example the content the card content needs a style with a gap in order to add spacing between inputs then the text input has this style with a background color but for that we need the theme as well so the text input has this style all of them and by theme we're gonna get using them use fim from Rec native paper just like that so now if I go this is the personal information then we have this one but we need to make sure to give the styles to our card as well to have a background color a lighter background color and Gap to the root container of 15. yes it's 15. all right so from delivery address we have cd postal code address and maybe we can do some kind of checkbox for them delivery for the shipping information like do you want a free fast or the same day delivery the component that we're going to use for that is going to be a radio button but more specifically we're not going to use them separately but we're going to use them as a radio button group having a radio button group a radio button dot group radio button yeah let's import let's go to the delivery sex and import them radio button from react native paper now after the address should we create a separate card for delivery yeah I think in this situation it will make sense to have a separate current I'm gonna copy this card once again uh and instead of delivery address we're gonna say delivery options or shipping options instead of this text inputs I'm going to delete all of them I'm gonna only be a card that content will remain and here let's render a radio button dot group and the radio button dot item inside it radio button dot item requires a parameter called value and label so for label let's start with a free value what's going to be the value of three and let's do the same for the hours as well I know fast and same day delivery okay now the radio radio button group component is missing the value and on value change so for the value you can you cannot do that using um State variable for the shipping oh come on shipping and set pink use state from react and let's use the value is going to be our shipping and on value change we're gonna call set shipping no will you have a value and let's send it to that oh because it's 95 so let's let's um let's pre-select the free shipping and yeah we already see it on the screen so now if I'm going to change to fast it's Gonna Change there as well yeah I think for this use case it's really nice to have separate cards for our here is where we will type something here is where we will select something and then we have next button um in cases where this is going to be a very long page we have to make sure that yeah for example if I'm gonna duplicate this a couple of more times like this we see that the button already is outside the screen in this case when what we have to do is to make sure that our screen is scrollable so from react native let's import scroll View and replace the top view with a scroll View and now we can scroll between them but the thing is that with a scroll view now the style should be content container style yes and in order to maybe hide them the scroll indicator shows vertical scroll indicator false yes perfect now we're this way we're going to make sure that everything is going to be basically accessible let me go ahead and remove the last two cards that I added there because it does only for repurpose to show Longs forms and how we manage them using scroll views and yeah I think it's safe to Simply replace it in the other forms as well for example in index the top view replace it with a scroll view make sure where you close it it's also scroll View and import it from react native foreign and the same can be done for our payment screen instead of view a scroll View closing tag and importing it from react native check out next from the delivery information we can press next and here on the payment information let's go ahead and start defining via inputs for the data on this page as well I'm going to remove what we don't need there we only have a submit button and let's actually from the delivery let's take the code of the card with these text inputs we're going to be a bit lazy and reuse some of these fields let's bring them to the payments.ts X and above our button let's drop the card we're going to need to import card and text input from react native paper and also the use theme because we have to make sure to import the film here as well use theme like this and let's navigate to that page delivery and we are on the payment information let's adjust the card because we will need other fields and the title will be payment details the first text input will be the card number maybe can provide a placeholder as well like I don't know for two for two for the postal code no we don't need the postal code here we need something else let's do a label label what um expiration date and something for the security code security code the expiration date is actually not a text input the expiration date is a date picker so let's look what react native paper has for dates so if we look at them do you see anything with dates here and remember that I saw date picker I don't know they actually don't yeah that's actually something extra so let's do for the expiration date let's just provide a placeholder with m M YY and we're gonna initially handle it using some validation rules and then maybe we can find and replace it with a more appropriate um input type there should we put the expiration date in the security code on the same line well we could by putting them inside of the same view that will have a style Flex Direction row let's import view from react native and if I go to the last page yes we see something and maybe that Charles need Flex one and the same one for the second one Flex one maybe some uh um for this view let's add a gap Gap 15. yes and here you can play actually like you can make the expiration date input twice as large as the security code or we can do three and this one too yes I think this is but better awesome and lastly we can look at our another component that can help us in this on this form is um switch let's use a switch to indicate if a user wants to save his payment details so what does a switch need switch value well basically the switch let's do it after this view as uh I think it should be in an hour view because we have a switch and then we have a text will be let's import text from Rec native paper what will the text say save payment information actually I don't uh let's first of all give it the style no actually I don't want this switch for this use case this switch is actually turning something on and off with saving user information I think that's more of um checkbox so let's use the checkbox it has also a checkbox item and I think instead of a whole view we can use a simple checkbox item imported from react native paper navigate to the last screen save checkbox item save payment information status checked or not it's going to depend on whether later on we will Implement that label variant there is a position where do we want to display it so position if we do leading it's going to be at the beginning yeah okay so if it's unchecked I don't really like because it's not very visible but it's um it's a checkbox but that's how it works on iOS to be honest so in that case I'm not going to do position leading because it makes more sense to have this filled here and be checked here all right perfect on Android and also on web I think it should look different so if I go to checkout next next yes here it's a proper checkbox yeah I was looking um we can actually add a Max wave to our cards and make them on on of on the web to look better maybe you we have to do this Max wave to the whole content container here and if we do a line self Center foreign but in this case it needs a width 100 percent to look on mobile devices and on the web as well so now we can see that this is responsive and if our screen goes smaller it automatically adjusted adjusts but if we have a blurry screen it's not going to display full width it's only going to display 300 pixels uh mean 500. so you can do the same content container style for for example with payments of our scroll View and also delivery and now all the screens are gonna look well on web as well nice all right so we have good progress um we have added the inputs most of the inputs that we need for our checkout form Maybe by then we're going to add and we're gonna work with other input Fields as well our input types as well but before we over complicate this tutorial I want to cover the the next part which will include managing these forms using react hook form and also validating them using Zod schemas and after that Advantage if we still have some time we're going to look into adding additional fields to the existing form and then it's going to make more sense because we will have everything already connected and we're going to see how we can adjust it so for that reason let me go ahead and do a git add here git commit minus m forms UI and we are ready to start with the next step by using graph hook form to manage these forms give me just one second I'm going to bring some water and we can continue I'm back um that's a good idea but you still have to have this index so what you can do is you can rename the index to personal come on personal uh in layout yes you need to change from index to personal and if we're gonna go to checkout we are we land on the personal but if on the web we're gonna navigate to checkout it will automatically redirect us to the personal because that's the first screen and we don't have an index yeah that's good yeah I think that's very useful because all the screens now have personal payment and delivery okay now we move into the interesting part of this tutorial so far we have implemented the user interface of our multi-step form now it's time to actually manage these forums whenever the user writes and fills that text inputs we need to know them the details about what he is writing we also need to validate whenever he presses submit to make sure that the data is valid and doing all of this without extra libraries can become really a complicated task in order to have all of this validation and all of these error States and so on so for that reason what we're going to do today is we're going to use react hook form to manage the form in combination with zond to validate our Fields based on a schema that we're going to Define so let's open the documentation of these two libraries first of all react hook form this is the library that we're going to use for managing performs and in the get started um it's where where documentation is targeted mostly at react application for web they have a little bit of documentation here for react native we're gonna we can start from here but I'm gonna show you how we can do it a bit better by creating some custom components that will help us do it because on react native it's a little bit more verbose and it contains a little bit more boilerplate to manage the inputs than on the web but that's not a problem because by doing a little a reusable component at the beginning van is going to be really easy for us to reuse it so react hook form okay let's install the library I'm going to do that using npm install react hook form let's do enter with the first library then I said that we're gonna need Zod .dav here is the documentation let's Zoom dark mode and we've thought we can um do this typescript validation and form validation based on the schema that we're gonna Define so what I wanted to show here I don't think oh it's form integration yeah we have a link here for form integration to to Showcase how we can integrate zodwith react hook form to do that we need an extra component called hook form resolvers that will allow us to make them connection between react hook form and Zod so let's go ahead and copy the name of this package hook forms slash resolvers and install it as well together with Zod so npm install hook form slash resolvers and Zod as well okay uh where do we start from managing the form or showing you the Zod I think the best place to start right now is to First Define our result schemas so what results came as these are a small schema that we Define how should our data look and using that schema we can use it to validate inputs and automatically get error messages based on the things that didn't match in the schema and also we can infer typescript types that we can use throughout our application to have type save validation and forums so for that let's go ahead and create an a directory Source in our application where we will keep all our source code including our schemas so in the source I'm going to create a new folder schema and invest schema let's create a new file checkout dot schema Dot TS Ruby x no it's TS it doesn't have any GSX bear so let's have a look at one small example of Zod schema basic usage we see what we have to do is import Z from Zod and then using Z dot object we Define we can start defining the shape of an object for example the shape of an user that contains a username of type string so let's start by importing Z from Zod let's define the we're going to create separate schemas for every single step of our form so the first schema is going to be our personal per come on personal info is going to be Z dot object and what Fields will our personal information contain one of them is the name and the name is going to be Z dot string and the number one is going to be email which can be defined as Z dot email I think it's uh dot string dot email like this and now if I export this no do I need to explore this one um okay okay okay before before we go next and use this person this Zod schema inside the hook form context let me actually let's let's actually player a bit around with this schema and see what we can do with it for example if I'm gonna have an object let's say example one with a name and let's say an email fake we can use this personal info dot parse method where we can provide an JavaScript object and back what we're going to receive back we are going to receive a typed object that has the name and has the email so now what I can do is probably I can execute this file let me see if I will be able to do it using node Source Dash schema Dash checkout schema cannot use import statement outside module um do I have to do anything special to get the web version no if you're using Expo router you can simply run the application on web by pressing on W in your um Dev server and it will run on the web but what uh what I was doing right now here is I executed this file that will try to parse um personal information data with a fake email and what we see here is actually we see a Zod error we validation code invalid string and we see that the path is email and if you provide a proper email and if we're gonna try to do npx test node again with schema we see that the info has been parsed correctly and it doesn't have any errors so with this approach yeah like what we we do with so we Define with schemas and then we can parse data to make sure that it fulfills the requirements of the schema that we provided and if it if not it will throw an error and it will have a very descriptive error message like in the case when the fake was not that was not an email so if we look at this we see that the messages invalid email you can also adjust these messages by providing by providing here in the email property the message please provide a valid email and if I'm gonna run it again we're gonna see that the message is the please provide a valid email so from this place we can adjust like what error messages we're gonna later display in our react hook form but as you uh and the number of things is of course inferring the type of our objects that we are managing there so for example if we want to type this info object with let's say the type of personal information what we can do is we can Define this type personal info equal Z dot infer and here we can provide type of personal info let's call this personal info keema and this type of personal info schema now this personal info we can use it like this to Define it here personal info schema like this so now this personal info schema was automatically it was a type automatically defined and created based on the object that we have here and I think if we provide here minimum one in that case name should become not optional I think it uh why it's not required is nullable is optional no let's do that uh here I'm gonna clean up the last rows that we were playing with and I'm gonna export these two things from here export const schema and Export type personal information let's go to the application check out personal here and let's start managing yeah the next step is to start managing the form that we have here with two inputs input using use hook form so for that what we need is we need to inform import the use is it use form hook or use hook form react hook form and yeah the hook is called use form let's go ahead and add the top of our screen let's define this form use four by using this uh by using this hook we we define basically a place where we will manage our form this hook will give us back a couple of things for example it will give us back a handle submit function that we should use to wrap our basically when we press submit button instead of directly calling the function of what happens when the form is successfully submitted for example going to the next page we need to unwrap this in the handle submit function and what this will do basically whenever we press on this button first things first it will validate that the form is um is correct and only after that it will go to the next page so now in the next page what we will also get is we will also get some data this data is going to be all the fields console all the fields of our form data form Fields let's do it like this data at the moment it's not going to work and if we're gonna look here I can press next and we are automatically redirect to the next screen that's because we didn't provide um a way for the form to validate um the input fields to do that what we can do is we can provide here in the use form an object and we're going to provide the resolver and the resolver is how do we want to validate um validate our fields and using that custom resolver let me actually check here in the documentation from react hook form we see Zod and here we show yes we need to import this Zod resolver and using Zod resolver imported from hook form resolvers Zod we need to provide here the schema and the schema is the one that we defined here personal info schema so let's import personal info schema and also the type personal info because we're gonna need this personal info as well the schema is going to be the Zod resolver used for our application and if you want maybe a bit later yeah now if I'm we're gonna try to do next nothing is going to happen we look at the at the logs actually nothing has happened happening why no errors nothing at all well basically our handle submit function try to validate the data that we were trying to submit and it's so that it does not pass the validation based on the personal information schema and the form returns some errors how we can get those errors we can get them by destructuring the form State and here we have errors so if you simply do console log errors you're gonna see that by pressing next here by pressing next we see that the errors is one error for the email the message is required the number one is for the name message also required okay that means that we cannot go to the next step because our form still has errors the problem is that at this moment we haven't connected our text inputs with our form here with with our form from the use form to connect it with our form what we should do is a couple of steps first one is we need to basically make these inputs text inputs we need to make them being we need to make them controlled by them use form and to do that we can we should destructure the control from a use form we should import a component called controller from react hook form here I am going going to show you step by step and then we're going to extract it into a separate component because it's a bit of boilerplate at this moment now having the controller component from react hook form and this control here what we can do is let's go where we have our text input let's add some space before it and let's start by rendering the controller component like this the controller expects the actual control which is the way we connect the text input with our form because this control is coming from the use form it also needs a name to know what is the name of the field that we are using here and it should match one of the fields from your schema for example name and when it has a render function the render function is here to render the actual text input so if I take this text input here put it in the render and re control of null what's happening check out yes let's try to write something if I press next if I look at the error messages it's still email required and name also required so that means that it's not yet finished like we haven't connected with controller with this text input in order to connect it this render function will give us access to the field properties the Field properties like what is the value of this field the function that we need to call when we change the value and the blur event we take these three events and we send them to the text input like this first of all value is value for the one change we're gonna hook it to the one change text because that's the that's the Callback function from the text input that will be called the function with a text field with a text string and on blur we're gonna simply say on blur now if I'm gonna do one two three and do next we see that the arrow is only for our email the name is has passed the validation we can test that that if we make our email maybe optional or nullable nullable and if I do next email required nullable optional yes optional and it works but if I'm gonna have some value I'm not gonna go to the next one why email is optional curvy before no never mind we we actually need it required I just wanted to show you that the name password validation but in case it doesn't pass the validation what we want to do is we want to visually show that somehow on the screen one way to understand if a text input has an arrow or not is using the object that we see here that we get from the form State errors but this one will contain errors of every field actually the controller besides the information about the field will also give us information about the field state and that information is for example the error so now using this simple error we can provide some properties to the text input for example error this one should be a Boolean right if I do it true it's gonna render with red yes so error Dot I heard that message no there is another property besides error like invalid invalid so for the error which is a Boolean we can send the invalid invalid and for the error message what we can do is we can yeah if I remove we see that it displays with red but it doesn't show the actual error message let's use another component from react native paper called helper text and this helper text rendered usually is used together with a text input and I'm gonna do that by wrapping them inside the view you and after the text input let's put the helper text so let's import view from react native oh it's here View and from react native paper we need helper text now in the helper text the type is error the visibility is going to depend on this invalid field and the error message will be the dynamic error.message cannot read message of fine Define I think error question mark message because error is not always check out and now if I'm gonna do next we see required perfect required so with this we have error messages as well to our to our controlled text input hmm I was thinking why yeah for example if we look at this value we see that the type is any the problem is that at this moment our use form doesn't know what data it is working with it knows how to validate it but it cannot understand the type of that data what we can do is we can provide them with data type to the use form as personal information and this is a type and that means that now the value will be a string because it knows that the value with a name name is a string and if we would use here a number it will automatically understand that this value is a number and it will automatically show us that hey maybe you're not using the text input right because the value is a number and on change should also receive a number so that's very good like that's very powerful where the simply the schema helps us validate our text inputs let's say I'm gonna go back to string here because the name is actually a string and now what now I think we are ready to do the same thing for the next text input then it will handle the email but as I said in the beginning using this erect hook in react native react hook form in Rec native is a bit verbose with this controller having to wrap all our inputs with a controller so now what I would have to do is to copy paste it again for the next text input but yeah it's gonna get out of hand out of control because if I'm gonna change something here I might forget to change it in another place instead what I think would be a good idea is to extract this controlled text input in a separate component and by sending just a couple of fields like what is the name what is the control and so on we can we can have a much easier component to work with in our forms so let's go ahead and in the source create a new folder for our reusable components and here let's have um controlled input dot TSX let's export default function controlled input and what should it return basically from the previous page let's copy everything here including the controller let's bring them to our page here we will need to import a controller from react hook form we will need to import a view from react native and a text input and helper text from react native paper text input and helper text the theme we need to get it using the use theme hook at the top of our component and yeah and that's it now the tricky part let's see what properties this control the input will get in order to make it actually reusable and easy to use first let's define the type of our control input props is going to be basically an object where first of all we will need the control here so control is of type control that we can also import from here now we can take this control Dynamic dynamically from the properties like this controlled input props now we don't have the red warning here anymore what's going to be the next part that will dynamically be sent this name like the name of the input that we want to render that's also going to be a dynamic property and it's going to be a string let's destructure this name from here and replace it with the dynamic name in our controller the rest of the things like placeholder label style value no value is coming from here and on change text as well and yeah beasts free are coming from here but the placeholder label and so on these are also properties that will be no style let's do it the same for all of them but placeholder and label will also be properties that we will receive from a parent component because all the text inputs will have a different placeholder or different label but instead of manually adding all of the properties that we want to adjust from the text input here what we can do is we can say that this controlled input extends the how do we take the react Dot com component props component props and here we need the component text type of text input and this way our con yes and now our control controlled input props will contain the two custom Fields controller name and also all of our properties from the text input now when we destructure it we can take the we can structure control name and we can put the rest of the properties that will be sent here in that text input input props now with text input prompts can be simply the structure here in instead of placeholder and label text input props like this the style we're going to be the same for all of them we want to change the background color value is coming from here when changed text looks well on blur yes I think everything else is coming from the controller now inside our personal TSX here let's import our newly created controlled input from our components and let's use it just below this controller by doing by rendering control input the control is going to be this control the name is going to be name and what else we also need the placeholder and label so let's put them here so just like that just with rendering this component with four properties we basically replace everything that we had here in 25 lines because all of this logic is inside our custom component control the input that simply wraps a text input inside a controller and properly sending the properties there so now what we can do is we can safely remove our previous controller from personal.tsx and instead of the next text input let's transform it to a controlled input where we have a placeholder we have a label we have style which we don't we already don't need to specify the Styles over and over because it's managed by the controlled input and we also have to send here two extra Fields control and name of a field what's the name of a field it's email now just like that let's refresh the page controlled input RR no let's go to checkout and now if I'm gonna press next we're gonna see that we receive the error messages both on the name and email I'm going to say by them here and press next if I'm gonna say I don't know Vadim next please provide a valid email and this error message is coming directly from our Zod schema we can do it like this we can and if you're gonna provide an actual valid email here is going to work and we can go to the next page all right so it does a lot but in order to recap simply what we have done right now is we started by defining the schema of our data where the form will manage in this case this specific form will have a name and email we Define how this data should look what validation should have what data types and what specific formats should it have we also provided a custom validation error messages and then we use this Zod schema inside our use form to use it as a validation method now with this use form we made sure to wrap our inputs inside the controller from our form and when we press on the button we are calling the handle submit that we also get from the form and this handle submit will schema to validate all of the fields and call this function only if the fields are validated or display the error messages on the screen if it's not validated if there are some errors like this one perfect so let's go ahead and commit everything and we're gonna do the same for the next two forums from for the delivery and for the payment I recommend I highly recommend you to pause the video and try to do it yourself for the next screens all you have to do is create new schemas for both screens and start managing the form using use form hook on the personal and the payment screen and meanwhile I'm gonna do commit oh hi Ahmed thank you very much could you make a journal taking application Rec native that's a good idea I think I will add it to my list of ideas so let's uh continue and let's do the same form management form validation for the next form for the delivery for example if we pass this one in redeliver we're gonna have City postal address and shipping options all right everything starts with defining the schema let's do here delivery form first of all let's export our Zod schema for delivery info keema that will be created using Z dot object because the information is an object it starts what will it have first of all City it's going to be a z dot string uh we can also do a minimum length of one for the postal code Z dot should be string I think it can be string let's start with basic validation and when we can come back and see how we can improve the validation by simply adding rules to this for to this schema so postal code is a string address as well as string and shipping um shipping let's look at Zod for enums Maybe zodenums okay so for the shipping we can use Z Dot enum and here we can provide the possible values for example free fast or same underscore day okay this is the basic schema for our delivery form we also need to infer the type of the of one of these objects so the type delivery info is going to be inferred from our schema just like that now let's go ahead in our word delivery page here what do we need we need the use hook use form react na I always forget react hook form we will need the resolver resolver from at hook form resolvers slash Zod resolver resolver is it like this oh we saw the resolver and we also need this schema that we defined the delivery info and the delivery info schema from our checkout schema okay now let's define the form using the use form hook let's say that we want to re the resolver the validation to happen using the Zod resolver delivery info schema let's say that this form is going to manage data about the delivery info about this type and we're gonna get back that control and what else do we need here we don't need the errors because we are managed at the level of a field I think only control yeah maybe now we're also going to need the custom component called control the input and instead of this text input we're gonna transform it to a controlled input where we only need to send additional two Fields the control and the name of this field the name of a field is going to be City then we have postal code let's make it a control input here we have controls and for the name we have what's the name in our schema postal code like this and lastly this one is also controlled input for the address send the control layer and the name is going to be address now if I go to checkout if I give some values here next and if I'm going to press next now no yeah that's what we also need the handle submit handle submit so in the button at the bottom of the screen we go to the next page only after handling the submit only after validating with the form is valid so now if I'm gonna press next we're gonna see that the city's required post record address is required and so on if I'm Gonna Fill them in I'm still not going to be able to go next because we still haven't validated the shipping options um the shipping options field because this is already not a controlled input this is a let's say controlled radio button let's go ahead and remember what we did previous time previous time to control an input we imported the controller from react hook form and we wrapped our component in this case our Rado button group inside that controller I mean we didn't wrap it directly here but we put it inside the render function so in the render we will render the radio button like this the controllers of the controller of course needs two extra properties the control and the name and name is in the schema we did it as shipping now the render will receive them field State including the value the on come on field state why typescript is not suggesting me value oh it's not field State it's field value on change and I don't think we need on blur here the value [Music] um basically at this moment we should switch from using a local state variable I'm even gonna remove it from here the shipping and set shipping which was a local state variable now it's not going to be as state variable it's going to be managed by form so for the value of this radio button we're going to use the value of the field and for updating it we're going to use on change and the value here is a string but it should be three faster same day okay let's uh let's do like this we still are not showing the error message so let's take the field State as well with them invalid and error and we're going to use them to probably what are we gonna do with it should we display a helper text above the radio buttons helper text let's do the same as here like helper text type error with an error message and helper textually be imported from the react hook form can we somehow skip the personal information page because I always have to add it to actually do that what I can do is simply put our delivery as a first screen here check out check out oh come on is it because of a delivery here helper text not from reactbook form I should import it from react native paper check out and we are on the delivery form if I press next we see that the error appears here as well and we actually need to select one of them how would we [Music] add default fields for example I want the free to be Auto selected I think to do that we can adjust it you in the use form hook so inside the delivery file use form hook here might be something like default values and for the shipping let's say oh look because it's typed because we typed it with this typescript it already knows what shipping can be there so I do fast if I refresh if I go to checkout it's Auto selected the first one I think I want you to do free check out and it's Auto selected with free and if I press next only now we can go to the payment information so that's how we created these how we implemented the form management and also validation for the second part of our forum for the delivery information uh okay now what you can do is you might want to extract this controller in a separate controller as we did with a controlled input that will be controlled radio button but then I don't want to do it because I only have it here so it's okay the controlled input is used way more often so it it made sense to extract it into a separate component you can do it as well I'm not going to do it just because I want to save a little bit of time so we are done with the basic validations on this page maybe we're gonna return back to add some more custom validations when we finish with the next form but for now let me do git commit minus m um delivery info form management perfect last step is our payment information so first in the layout I'm gonna put the payment information at the first screen in order to now if I'm going to press checkout I'm going to be redirected to the payment information because this is the first one here so payment information let's open up the payment information page and we will also need to open up with schema because we need to define a new schema for our payment form let's start as we did previously by defining the payment info schema using Zod it's going to be an object and what information will it have it will have card number Z dot string it will have expiration date see I'm gonna do zero string for now and just to connect everything together I see security code Z dot string CQ write your code and lastly we're gonna have um save information as a z dot Boolean okay so let's also make sure to export the type of payment info using Z dot infer type of delivery info perfect now let's open our payment.tsx component and here let's start by importing everything that we need we will need the use form react to form we're gonna need the Zod resolver hook form resolver slash Zod and we're gonna need them payment info and payment team for schema from our checkout schema let's go ahead and Define our form const use form here we already know that we want to define the type of our data to Dynamic type there and as a resolver we're going to provide the sword resolver using our schema okay and uh we're gonna get back here that control and the handle submit for the handle submit we're gonna we already know what we have to do is we're gonna wrap our function from their own press event in the handle submit and if I press right now nothing happens because we get errors and the control is going to be used for the text inputs because we're going to change from text input to controlled input and we're going to provide here the control and the name how's it number yes it's number then for expiration date it's also going to be controlled input and for the name it's going to be expiration date we don't need additional styles actually for this one we need the flex hmm we'll see how it looks so let's make the last the security code also controlled input yeah it um let's see if from control the input now it doesn't have a flex one and it doesn't look very well there so if this view will have Style Flex one yeah I think it works I hope it works for it didn't broke in our places but we're gonna see a bit later for example in the first the card the number it didn't break it so I hope it's okay and lastly all our inputs became controlled and this checkbox we should also make it a control checkbox we're gonna do that using the control component not like this we need to First import it from react hook form controller and we're gonna add it here by specifying the control the name which is save info is that how saving for yes and where render is going to be this checkbox what payment info oh wait a second I think I made a mistake here invest schema because I need to infer the type of payment information schema yeah now saving for it works and the status if it's checked or not is going to be determined by the form value so form value is going to be I always forget is it feel not form field so the value now if we look is a Boolean so here for the status we need to send check to unchecked and we're going to do that using a value is true then it's checked otherwise it's unchecked no it's unchecked if I press nothing happens because we should do on press we're gonna call their on change on change and we're gonna revert the value yes now it works to save information we're not now it works now it redirects to the home page really if in layout now we're gonna put payment is the last screen and if we're gonna refresh our page and we're gonna go to checkout we're going to have validations for reverse screen we're going to input it name email next for a delivery we cannot go to the next one we need to provide information about address CT and so on next and here we cannot go to the next screen we need to do like this and save payment info submit and we are on the checkout page I don't know why right now it works but good for us foreign validation for management for the last step in our multi-step form for the payment details so let's go ahead and do git add git commit minus m payment info form management okay what we have right now is we have free independent forms that all manage information about what they need for example the first one manages information about personal information then we go to the next one the other one is managing information about delivery and the last one is about payment we think is that when we get to the last page and we press submit in a lot of cases we at this moment when we submit things we need all the information that we covered in the previous steps the problem is that at this moment in this payment screen we only have information about the payment information we in a way will lost information about the personal and delivery forms because they are different screens so in order to manage all of us separate independent forms as one complete flow what we're going to do is we're gonna use react context to manage this data at a higher level than the screen level what we're gonna do is we're gonna Define our react context that will contain all the data about personal information delivery information and payment information it will wrap all our screens from our checkout page it will not wrap the whole application because we only need this checkout screens to contain this information and then on the last screen when we press submit at that moment we're gonna have all of the data collected in our react native context so for that what we have to do is to create the context let's go ahead and in the source create a new folder contexts and in the context let's create checkout context dot TSX first things first let's define the checkout context let's create it using Create context that is imported from react and we're going to initialize it with an empty object to make it type safe we're also gonna do the checkout context type which initially is going to be an empty object as well but we will be able to specify the type of this context right away so now this is a checkout context type okay the checkout context right now contains two things the provider and the consumer so first of all using the provider I'm going to export default this function which is going to use the checkout context provider and check out context.provider it will send the value to this provider which initially is going to be an empty object and inside this provider we're gonna render all the children that the checkout context provider component will receive so here children oh okay okay let's do a test and hear ABC now I usually also like to export a custom hook that will uh give us that will consume this checkout context and that hook is going to be called let's also export const use checkout context is going to be a custom hook that will simply call the use context and will provide wherever checkout context and later instead of importing two things use context and checkout context we're only going to import one thing this use checkout context now we have a boilerplate of our checkout context we need to wrap our screens that depend on this checkout inside this function inside the checkout context provider the screens are instead of wrapping our root layout the same way as we did with a paper provider to do the same with a checkout context provider instead of doing that basically I don't need information about the checkout form on every screen of our my application I only need it to the screens inside the checkout folder with delivery payment and personal so our driver encapsulate the screens inside our underscore layout from the checkout page to only have these components they depend on the checkout context so let's import checkout context Provider from there and wrap our stack with it now in order to understand if our screens like personal delivery and payment if they have access to this context we have here a value test so let's go ahead in the personal and at the top of our function I'm gonna remove the errors let's do const test from not from but equal use checkout context that was imported from here now if I do console learn test we should see the warning ABC here which means that our screen has access to this value from the context provider okay now what we can do is we can add State variables for our personal information for our delivery information for our payment information I'm thinking here whether V should be State variables in them whether we should manage the state variable of them already validated data or if we should maybe move a whole use form to the context provider I actually don't want to do that I really want to leave the low level of form management to every individual screen and in the context provider here I don't want to think about forms I want to think about data so in this situation I will have free state variables one for the personal info I will do personal just to keep it short not to do personal info set personal info set personal this is going to be a use State and the value is going to be null initially but the type is going to be imported from the personal information from our result schema so in that checkout context the type is going to be personal info imported from our schema the same thing we're gonna have for delivery set delivery this is going to be delivery information initially null and I think we also should say so so this would say should do or null or null and lastly it's going to be our payment information set payment info payment info or null and like that now our value is going to include all of this data basically personal information set personal information I'm not sure if we need the values to to expose the values we can expose the Setters because we will use them to save data in the global context like this it should be inside an object like this and now our context type will include this set personal which if we look at the type of a set personal easier react dispatch set action and the type of a set action is going to be personal information then we're gonna have set delivery which is going to be a react dispatch set action delivery information and the same thing for the payment set payment this one is payment info maybe also null as well if we want to reset it maybe yep yeah or no let's let's not do like ah okay Now the default create context here will say that hey we need to provide some default set uh payment and set personal and so on so let's do a default one which is going to be an empty function uh thing set delivery as well and lastly set payment as well uh [Music] and let's also expose a function called on submit all that will be called in the last step so meet all submitting the multi-step form and let's console log here personal let's console log here the delivery and the payment and payment so let's also export this on submit function but we need to specify the type so in the type on submit all is going to be uh function that doesn't return anything and the default value will be like this you don't like it should be void no what oh okay okay so having uh exporting free centers to save a set personal save a set delivery set save a set payment in our Global context and then a function also meet all that well display and basically will write into our console all these details we can go ahead and connect this information to our actual forms the first one is our personal and here uh in the use checkout context let's get the set personal uh and this set personal we're gonna use it with this data the data next page function is called by the handle submit this handle submit will send the data and this data will basically be of type personal info now because it's of type personal info we can go ahead and set it in the global checkout context as data set personal data now the same thing should happen in the delivery uh here we're gonna get them use checkout context and we're gonna receive a set delivery the next page will receive a data with delivery info and we can use it to set delivery data now in the payment here we're gonna receive data of type payment info we need that const ant use checkout context and use checkout context will receive a set payment and also their own submit all function the first step is to set payment as data and the second one is their own submit all which in a real scenario will actually be will actually be in a sync function because usually you have to wait to to submit this data to a server and that isn't async function so let's change this from normal function to a sync should be a promise should we do promise Dot Boolean and return true if everything goes okay and return false if there was an error submitting it to the server Maybe so here I don't know promise dot resolve false and also it all will become a sync and will return true now in our last screen in the payment in screen we're gonna do const re uh success equal a weight on submit all and here we can check if success is true only when redirect of our page otherwise Let's do an I don't know alert alert failed to submit the form for some reason and this failure is not necessarily related to the form validation because at this point we know that the form validation passed this is actually a uh this is actually because of um if there is some problems with pushing the data to the server maybe the user doesn't have internet connection so on submit all let's check it out so Name by dim email next we're gonna also keep an eye on the console because at the end we should display this so like this I want free delivery maybe fast delivery next and payment information so it's like this and expiration date like this and security like this and save and let's do submit now it says submitting the multi-step form we have a email we have a address but the payment information is null you know why it is null it is no because we are calling the setter which is a state and the submit all function basically one after another but we should remember and actually I had a call with a coaching call with one of a startups that I'm coaching and that was the issue that I was explaining them um to to keep it to keep track of because updating a state variable doesn't update the actual value right away it will only update it during the next re-render so basically in this case we are scheduling the set payments to update and also meet all we when we call it during the same time like we do not have it yet so maybe maybe also meet all hmm maybe we can send this data to the on submit hall because this is the last step let's try that even then like I don't don't quite like it better think with a challenging one how do you do it properly like one way would be to send this data to the own submit all and then send the data here and yeah like in them in the checkout context to receive it here as the payment information but in that case we are not going to have a state for the payment and it's a bit weird that all the steps have a state variable and the last one doesn't have one submit all I could do it with some kind of awesome some some kind of states and use effects but I don't see it very it's a very optimal solution nads guys foreign [Music] State maybe I'm Gonna Leave a payment state but I'm also gonna receive it here as payment info payment info so now my now here I'm gonna do a set payment payment info and I'm not gonna depend on this payment in this method but I'm gonna depend on this payment info variable because the state might not be updated yet but I'm pretty sure that what I receive as a parameter is going to be the latest information now in the payment here I can leave a statement payment but it's optional here because all I have to do is send the data to the own submit all and we'll submit all here we'll receive payment info of type payment info let's check right now if I do save now we see a souvenir multi-step form with this data email and name then address City postal code and shipping expiration date number save information through and security code so now we see that when we press on submit in the last step we actually uh have access to all the information that we covered in every single step of a form up until the last part so with that being said I think we are done with the implementation of managing the multi-step form as a one where we get data from every single step of uh of that multi-step form so let me do git add git commit uh okay what else what else what else what other things are you interested in should we improve a bit the form validation rules because at the moment a lot of them are if we look in the schema in the checkout schema a lot of them are simply strings so let's have a look at them documentation from Zod for Strings and here are some of the specific validations this minimum and maximum will specify there are external validators contains is after and so on so what do we want to do here for example regex is a is a cool one uh what we see here like is how we can provide uh the default error messages for them require property so instead of saying required you might want to adjust it to say let's say in the name when we say string for the required error we can say name is required and now it's gonna actually say a more descriptive error message instead of a default one required you can do that as well what else can you do using the length what we can do is on the last screen for the payment information for security code I think we can specify the length of free because all security codes should be three digits long so if we provide here also a message security code should be a free digits three digits long what else can we see here this is for days but we're not gonna directly parse dates IP addresses for numbers you can specify greater than lower than if it's a positive negative if it's an integer so it's very very powerful like oh so optionals is the optional and when you put it inside the type or you can do dot optional uh look with the we've emerged I think we can use the merge to merge all of the data at the end into one single uh object right so if we have one object one base teacher merge foreign so for example if we go into the schema and if we want to Define a schema for our checkout info check out info schema that's going to be a personal information schema dot merge we're going to merge with deliver information schema and can we do a DOT merge again yes we can using payment info schema okay and yeah we can export this one but most probably weren't only gonna need the checkout data Maybe check out data which is a type and this type is going to be equal Z dot infer type of checkout info schema now let's check our data can be in our context for example if we want to to specify the data that we want to send to the to the server check out data which is of type checkout data and if I do it simply as an object I don't think it should work if I do ABC a it says that ABC is not there but if I do the structure where the personal data and also the delivery data and also the payment information we can basically have all of them together as checkout data now if I'm gonna do fill in this form security code should be three digits one two three submit if I'm going to look in the console log we see that all of the information that we covered like with address with email name the security code postal code and so on all of it was merged together into the same object and it is properly type safe with all of the information that it has and usually you would want to do that because when you send data to the server yes on the front and on the user interface you split it in multiple screens in order to make it much easier for the user to fill it in but the server will still expect basically a bunch of data into the same object so if that's the case you can do that like this and on the schema side you are simply merging different schemas into one okay what else can we learn from Zod partial it's when you only take some some properties from there arrays you can manage arrays unions promises functions like ever everything all the data types can be managed with Zod foreign [Music] let's let me show you how we can transform data types for example um if I'm gonna look at the you know what I'm gonna I'm gonna work a lot with moving around the screen so I think I'm gonna provide some default values let me go to the personal here and for the use form let's do default values for now as name email the same way with delivery let's go for the use form where is it use form uh uh what do we have here CT we have postal code one one two three we have address great a H what else what else so from checkout I can go next here I can go next and we are on the payment side if we look at the schema we see that the security code at the moment is a string should it be a string or should it be a number type because if it's a string it can be AAA but I think security codes can only be digits so we could go ahead and reply uh change it from a string to a number let's add the where the number doesn't have a length the number can have minimum let's do minimum 100 where let's do let's check uh for the number numbers greater greater lower let's do greater or equal than 100 and then lower were equal than 999. to put it between these two to have a three digits number uh now the thing is that the error is expected number received string but probably is that at the end of a day like the text input is working with string what we can do is by providing um to the security code here let's do coercion if I'm gonna do before the number if I'm gonna do dot Co errors number in this case what will happen is Zod will apply the number where is it the number Constructor to transform the string from a string to a number this works with strings with numbers with booleans with begins and with dates so now we actually are are writing numbers and the security code is working as a number if I do a expect a number receive none so in that case it cannot parse from a string to a number what else what else for the expiration date here I think what we're gonna do is we're gonna provide them we're gonna provide the regex for the expiration date so let's use charity to get this regex um JavaScript regex for mm YY let's break it down so the start of a string the Month part it allows two digits from zero one to zero nine where 10 and 12. then four digits for the year okay let's take this one and in the schema where we have expiration date for the string let's do Dot regex and here provide these regex and if I'm gonna do submit it doesn't allow if I'm gonna do two to two invalid if I'm gonna provide 0 to then 2022 it works but should be greater than it should be in future allow only uh dates dates in future it's a bit more complicated uh but not sure if it's the best idea to um to do the future if it's a future date validation using uh uh using regex maybe we can add something custom there for example Rejects parse data given any thoughts schema you can call its parse no parsa sink no safe safe refine this one we can do it with this so lets you provide custom validation logic via refinements for advanced features like creating multiple issues and customizing error codes using super refine or who I don't need Super refine uh uh so what we can do is yeah like we can specify um oh I can add it on web type itself so look what I'm gonna do I'm gonna refine this expiration date it's a regex that's going to be the first rule but I'm also going to add some custom logic here so value this is value uh chair gbt helped me parse it to a date uh GS parse as string with format mm why why why why to date it's for a splits and then it okay let's do it like that uh V3 refinement is going to be a function for me the date string is going to be our value we're gonna split it by slash and then the date is going to be parseer parse month minus one and we're gonna return date trade return true or false I don't know let's let's check if date is more than new date which is today and the second parameter over refine is the message where we can provide the other message um card is expired so now with this refinement if I'm gonna submit now it works but if I'm gonna do 25 yeah I think it should be a valuable way around like date return true basically return that there is no error if the date is in future so now if I'm gonna do 25 it's okay but if I'm gonna do 21 card is expire 22 card is expired 23 is expired if I'm going to change to 0 8 it's in future yes so that's actually very powerful so with a simple function we added very custom validation logic to our field and the cool thing about refinements that is that they can also be asynchronous meaning that you can call your server to validate a field and where this might be helpful it might be very helpful where you have something like a unique password validation your user will type a password with a refinement you're gonna query your server to see if the username is already taken and if it is you're gonna display an error message saying that hey this username is already taken what else what else uh with a card number let's do with a card number as well how should we validate card numbers validate card numbers I'm thinking what's the best way should we have spaces between the digits or no hello regex for credit card number come on okay I think I like it so let's take it it will actually match Visa masterclass American Express discover and so on so here let's do const card number regex equal to this one well it's a problem here so this is a very long credit card number right checks but we can use for the payment information number it's a string but it should match your regex of this so if I'm gonna do one one invalid I'm gonna do four two four two he doesn't like the spaces so you can remove the spaces still doesn't like it at least 12 digits as I understand it should start with four and one two three four five six seven eight nine 10 11 12. okay oh okay yes yes as you can see it actually works and now our payment information is properly handled using the number the expiration date security code and whatever to save information or not submit and if we look we see you can do the same with a postal code with an address maybe address you cannot do but with postal code I think there are regexes for that as well with a city maybe you can I don't think you need to do anything with the city um yeah I think that's most of the thing that I wanted to show let's go ahead and get add git commit minus some additional validation and let me see what else what else should we do um let's say with these refinements that I showed you you can also add additional validation that depends on different fields from your form for example if you want to provide a password and confirm password field in that case what you can do is yeah let's say you have I will add it to the personal information schema so we're going to have a password which is a z dot string and a confirm password which is also a z dot string let's go ahead in our checkout personal information and let's add two more control inputs for our password we don't need a placeholder we need a labeled bus word and another one for confirm password kind of firm password and confirm password you can also add here a property secure text entry secure text entry but for now I'm gonna comment out secure text entry because I want to show you something come on if I'm going to press next we see that the confirm password is actually required if I come on refresh I checkout if I go next we see that with password and confirm password is required but I can do one two three and here four five six and I can press next and it goes to the next page so at this moment we are only validating that the password and confirm password are there but we are in no way validating if they are actually matching we saw how with refinement we can provide custom validation but how can we do based on two fields and the schema because we cannot do refine here as only data but we'll receive is the password and we cannot do it on the confirm because as well we need both of them what we can do is we can add the refinement on the whole object of the personal information sorry fine here we're gonna receive data and what we should return is let's return um I don't even need the body like if password if data dot password is different than data dot confirm password then that's going to be an error and as the second parameter I'm going to send the message passwords don't match so I think I should do if it's equal not if it's different and you find it's not a function and personal information and you find it's not a function because it has this refined there's a problem there Z dot object password and confirm refine yes Puff puff over error maybe we can specify where there are I did is to the confirm password still the merge function is broken right now maybe we can do whatever way around we're gonna merge the personal information inside that one yeah weird so now if I do next we see that the password don't match and I should do one two three and then the error disappears because our custom refinement that works with data password and Compares it with a confirmed password is returning this message in specifying with path it will assign it to this custom password as an error not custom but confirm okay so that's something else get and get commit minus m password validation all right guys so I think I'm gonna stop here because we covered quite a lot of use cases with this form uh what I'm gonna do right now is I'm gonna go ahead and from the personal information I'm gonna delete these default values for my name and email from the payment I'm gonna do it doesn't have anything delivery I'm Gonna Leave only the shipping to free and now I can do get add git commit minus um clean up I think we can do some extra cleanups like in every file from our um from our Pages like from delivery we don't need a link here we don't need the use date anymore we don't need this text we don't need this text input and that's it from the payment we don't need the link text input switch text [Music] that's it foreign as well let's clean the unused import ant no it doesn't like this this way and let's have a quick look at what we managed to build let me also open it on the web you know foreign all right guys so in this tutorial what we learned so far was to build a multi-step complex form in Rec native uh that is going to be managed and it's also going to be type safe using react hook form Zod export router for the navigation between screens and our interesting tools and that made this project really easy to to implement it was yeah like a bit complicated to set everything up but in the end now it's very easy to adjust things it's very easy to add additional validation information or additional fields and so on so what we can see is initially if we press next here we see the validation errors let's go ahead and fill this one for example if I provided invalid name it right away tells me for the password it will make sure to mesh the passwords and I think I should hide them but that's not the biggest problem now with a mesh I'm compressed next and we go to the delivery information after you fill in the delivery information with your details you select the shipping option you can press next to go to the last step with the payment information here if you simply press next you see that the card is the card number is properly validated the expiration date should be something in it should be something in future it will validate that as well like 24 and for the security code as well it should be a three digit find on Android as well and also on web here on the left you see it on the web and it will show the same error messages as we saw previously I hope you enjoy I hope you enjoyed this tutorial and if you did make sure to subscribe to the channel and uh turn on the notification Bell not to miss our future videos because we are going live every single Friday with new tutorials um I also want to tease something so if you're watching this right now keep an eye to our academy.nojs.dev which is our premium course keep an eye on it during the next week because we might or might not have something special for you and if you are a virtual video till this moment um send me a message let me know because I might have something interesting for you and if you are watching it here that means that you are dedicated to learning full Stack mobile development alright guys have a nice weekend ahead uh and I will see you next time with a new project bye bye
Info
Channel: notJustā€¤dev
Views: 2,402
Rating: undefined out of 5
Keywords: vadim savin, not just development, notjust.dev, react native live coding, live coding, javascript, react tutorial, react native tutorial, javascript tutorial, react native ui, react native for beginners, first app, App Building, React Native, Google Forms clone, React Native forms, form validation, Zod, TypeScript, schema validation, form building, form validation tutorial, React Native forms tutorial, Zod tutorial, TypeScript validation, form handling, react native ui design
Id: Z9TffIGhYAE
Channel Id: undefined
Length: 208min 31sec (12511 seconds)
Published: Sat Jun 24 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.