1 00:00:02,530 --> 00:00:05,110 So how else can we optimize this? 2 00:00:05,110 --> 00:00:11,350 Well you might notice that this jsx code here in end can be repeated over and over again, every input 3 00:00:11,360 --> 00:00:12,590 looks like this. 4 00:00:12,640 --> 00:00:18,130 We have a view, we have a label with the text input itself and we might also want some error text which we 5 00:00:18,130 --> 00:00:19,140 can display. 6 00:00:19,270 --> 00:00:22,900 So it would make sense to outsource this into a separate component 7 00:00:22,990 --> 00:00:25,370 and that's exactly what I want to do. 8 00:00:25,480 --> 00:00:32,230 I'll go to my components folder and there in the UI folder, I'll add an input.js file which will hold 9 00:00:32,230 --> 00:00:38,410 a React component, so I import react from react of course and then import a couple of things from React 10 00:00:38,410 --> 00:00:45,460 Native and these things in the end are my view, text component, the text input component and the stylesheet 11 00:00:45,460 --> 00:00:54,210 because I'll need this as well from React Native and with that here, we can create the input component 12 00:00:54,210 --> 00:01:01,410 here which gets props and needs to return some jsx. We'll have a styles object with Stylesheet.create 13 00:01:02,780 --> 00:01:08,230 and of course in the end, we export this as a default here, this component. 14 00:01:08,340 --> 00:01:18,420 Now if we go back to the edit product screen, we can cut this title jsx code, so the surrounding view, 15 00:01:18,440 --> 00:01:23,890 the text, the text input and this error message part, cut it out of here, out of the edit product screen 16 00:01:24,250 --> 00:01:32,700 and move that into the input screen and there, use it as a return value in the input component here. 17 00:01:32,740 --> 00:01:37,210 Now of course, we'll need to adjust this a little bit but that's our general skeleton which I want to use 18 00:01:37,210 --> 00:01:37,720 there. 19 00:01:37,960 --> 00:01:42,720 Now also from the edit product screen, I'll take the styling, there 20 00:01:42,770 --> 00:01:49,270 this form control label and input styling can all be removed and should be moved over into the input 21 00:01:49,270 --> 00:01:55,440 component and there into the stylesheet. 22 00:01:55,460 --> 00:02:00,740 So now with that of course, this only can be used for a title and I want to create an input component 23 00:02:00,740 --> 00:02:07,580 which can be used for any input, that for example means that the label here needs to be dynamic, 24 00:02:07,710 --> 00:02:10,830 so I'll expect to get this on a prop named label maybe. 25 00:02:13,740 --> 00:02:18,420 I also in general want to make sure that the text input can be configured from outside, 26 00:02:18,420 --> 00:02:25,800 so I will forward all props I get on my input component here to the text input, so that on this input 27 00:02:25,800 --> 00:02:31,060 component, we'll be able to set things like the keyboard type because I don't want to hardcode this 28 00:02:31,070 --> 00:02:31,570 in here, 29 00:02:31,570 --> 00:02:36,720 instead this should be a reusable wrapper around the text input component which can be configured from 30 00:02:36,720 --> 00:02:37,570 outside. 31 00:02:37,800 --> 00:02:43,990 So these settings here for example, I will cut them from here so that we can set them from outside, 32 00:02:44,010 --> 00:02:46,530 I'll also get rid of these listeners because we don't really need them. 33 00:02:52,130 --> 00:02:57,230 The error text here should also be settable from outside, so I will check for props 34 00:02:57,230 --> 00:02:58,640 error text here 35 00:02:58,640 --> 00:03:02,720 and of course you can as always give these props any names you want, 36 00:03:02,720 --> 00:03:07,570 of course we'll also have to change what we assign here as a value and so on, 37 00:03:07,570 --> 00:03:08,800 that will also change. 38 00:03:09,350 --> 00:03:11,720 But now we can already start using that input here, 39 00:03:11,720 --> 00:03:23,200 let's go to the edit product screen and there, I will just go to the top and import input from the components 40 00:03:23,200 --> 00:03:27,210 folder of course and there from the UI folder and there from input 41 00:03:27,550 --> 00:03:32,770 and then we can start using the input component in the place where I previously had my text input component 42 00:03:32,770 --> 00:03:33,910 here. 43 00:03:34,000 --> 00:03:40,510 So there, I will just add input and now on input, we can add the setting which I cut, like the keyboard 44 00:03:40,510 --> 00:03:43,000 type and so on because that will be forwarded. 45 00:03:43,180 --> 00:03:50,950 We can set our title label, like title and also our possible error text like Please enter a valid title, 46 00:03:51,550 --> 00:03:55,470 though that's not all we'll do regarding validation but it's a start. 47 00:03:55,510 --> 00:03:57,250 This is how we can then use this input 48 00:03:59,130 --> 00:04:02,970 and of course this is also how we can now use it to replace the other inputs. 49 00:04:02,970 --> 00:04:11,400 So for example here, the imageUrl, here I set this to imageUrl, Please enter a valid imageUrl 50 00:04:11,400 --> 00:04:17,910 maybe, keyboard type default is okay, auto capitalization auto correction is not required, return 51 00:04:17,910 --> 00:04:18,480 key type 52 00:04:18,480 --> 00:04:23,070 next we can leave that, we're not doing anything with it, we could add some logic but I'm not doing it 53 00:04:23,070 --> 00:04:29,990 here. For the price I'll leave the conditional rendering but in there, I can add my input here, 54 00:04:33,510 --> 00:04:42,300 set this to price please enter a valid price, keyboard type here should of course not be default but 55 00:04:42,330 --> 00:04:49,380 decimal pad, don't need auto capitalization or auto correction so let's get rid of that. And for the description 56 00:04:49,380 --> 00:04:58,740 here, I'll also add my input here, description, please enter a valid description, keyboard type can be default, 57 00:04:58,980 --> 00:05:05,700 I can use auto capitalization, auto correction, however I'll not set a return key type but here I want 58 00:05:05,700 --> 00:05:14,330 to set multiline just like this which allows for multiline editing and set number of lines to let's 59 00:05:14,330 --> 00:05:15,830 say three. 60 00:05:15,830 --> 00:05:20,630 This however is only used by Android but there, it will restrict the number of lines you can enter, on 61 00:05:20,630 --> 00:05:25,580 iOS, this will not have an effect but this is how you can now use this input component and still configure 62 00:05:25,580 --> 00:05:27,470 it from outside. 63 00:05:27,470 --> 00:05:30,240 That being said, as I said we're not done though, 64 00:05:30,260 --> 00:05:35,710 what about the value and this change text listener? 65 00:05:35,840 --> 00:05:42,030 There are different ways of how you could handle this text input or the text values here. 66 00:05:42,050 --> 00:05:47,960 You could still simply forward it to the parent component and only use this input component as a visual 67 00:05:48,080 --> 00:05:49,020 wrapper 68 00:05:49,310 --> 00:05:55,850 but I will take it a bit further and I want to manage this value and the validity of this single input 69 00:05:56,180 --> 00:05:58,460 inside of the input component, 70 00:05:58,460 --> 00:06:05,280 so that I then only report back to my parent component, so to the edit product screen in the end what 71 00:06:05,280 --> 00:06:07,900 the current value is and whether it's valid or not 72 00:06:07,940 --> 00:06:11,980 so that validation doesn't need to happen inside of the parent component 73 00:06:12,170 --> 00:06:17,480 but again that is totally up to you whether you want to do that or not. Here 74 00:06:17,480 --> 00:06:25,520 I will add a new constant in the input component, text change handler where I get this enter text because 75 00:06:25,550 --> 00:06:31,400 that's now what I bind or what is already bound and I will generally keep it like this, though we don't 76 00:06:31,400 --> 00:06:33,380 need the identifier here anymore, 77 00:06:33,620 --> 00:06:39,560 don't need bind therefore because this is inside of a single input, we don't need an identifier 78 00:06:39,560 --> 00:06:40,810 there. 79 00:06:40,880 --> 00:06:44,150 This will now therefore trigger on every keystroke and hence 80 00:06:44,150 --> 00:06:56,140 now here, I want to check whether this is valid or not and also manage my value of that input. Now for 81 00:06:56,140 --> 00:07:02,270 that, we can again use a reducer or individual states managed with use state or created with use state 82 00:07:02,300 --> 00:07:03,920 but I'll go for a reducer 83 00:07:04,090 --> 00:07:12,300 and here I have my input reducer, name is up to you, gets the state, gets an action and returns a new state 84 00:07:12,300 --> 00:07:13,110 in the end. 85 00:07:13,440 --> 00:07:20,390 Then here into the input, I can call use reducer and forward or set this to the input reducer 86 00:07:20,550 --> 00:07:28,200 and my initial state for this input here will be a simple Javascript object with three values. The value 87 00:07:28,260 --> 00:07:34,470 which you currently have, which initially can be empty but actually I want to allow myself to set an 88 00:07:34,470 --> 00:07:37,230 initial value from outside because we will need this, 89 00:07:37,260 --> 00:07:41,570 for example when we're editing products, so I check whether props 90 00:07:41,610 --> 00:07:43,700 initial value is set, 91 00:07:43,700 --> 00:07:46,980 again this is of course a name you can choose however you want 92 00:07:46,980 --> 00:07:49,220 and if this is the case, I'll set this to props 93 00:07:49,230 --> 00:07:50,040 initial value, 94 00:07:50,130 --> 00:07:53,460 otherwise I'll set out to set this to an empty string, 95 00:07:53,460 --> 00:08:03,600 then I will also manage whether this is valid or not and there again I can check if props initially valid 96 00:08:03,630 --> 00:08:05,160 let's say is set. 97 00:08:05,160 --> 00:08:08,780 If that's the case, then I will automatically take that value which should be true or false, 98 00:08:08,790 --> 00:08:11,750 if it's not the case, this will automatically be treated as false 99 00:08:13,420 --> 00:08:16,440 and I will also manage whether this has been touched yet or not, 100 00:08:16,450 --> 00:08:23,170 so whether the user did actually type here and this can be useful for helping us with providing a better 101 00:08:23,260 --> 00:08:26,850 user experience regarding when we show validation errors 102 00:08:27,100 --> 00:08:33,760 and here I will set this to false initially. 103 00:08:33,780 --> 00:08:40,260 Now of course, this will return us the input state snapshot and a dispatch function which I here can 104 00:08:40,260 --> 00:08:46,920 also name dispatch because we will have no name clash and in the text change handler, of course I will 105 00:08:46,920 --> 00:08:54,420 dispatch an action, an action which I therefore will create here with an action identifier, input change 106 00:08:54,420 --> 00:09:00,040 for example, that should be dispatched here, 107 00:09:00,040 --> 00:09:08,930 type input change and then here in the reducer, we can add a switch statement to mix things up, check the 108 00:09:08,960 --> 00:09:16,150 action type and for the case input change, we want to do something. In the default case, I will just return 109 00:09:16,190 --> 00:09:22,400 my state, so I will not do anything but here of course, I want to do something else. 110 00:09:22,630 --> 00:09:27,730 Now here in the text change handler, obviously I dispatch input change and I want to forward the value 111 00:09:27,760 --> 00:09:29,320 which I stored in a value key 112 00:09:29,410 --> 00:09:35,320 but now here, I also want to do input specific validation and forward the information whether the input 113 00:09:35,350 --> 00:09:39,550 is valid or not. And for this, attached 114 00:09:39,570 --> 00:09:45,040 you find some validation setup or some validation code which I'll now walk you through. 115 00:09:45,210 --> 00:09:50,760 Here I have a constant that sets up an email regular expression, so a regular expression that allows 116 00:09:50,760 --> 00:09:52,710 us to validate email addresses, 117 00:09:52,710 --> 00:09:58,290 we have no email address input yet but later when we add authentication, we will have that and then I 118 00:09:58,290 --> 00:10:00,670 want to be able to use this input component, 119 00:10:00,780 --> 00:10:04,580 so then this component should be prepared to also validate emails. 120 00:10:04,740 --> 00:10:10,140 Then I have the is valid helper variable here because then we have a bunch of checks here. 121 00:10:10,140 --> 00:10:16,610 Now I want to make sure that we can set the criteria we want to use from outside with the help of props, 122 00:10:16,620 --> 00:10:21,030 so for example I check if a required props is set, if that's set to true, 123 00:10:21,030 --> 00:10:26,610 so if it's set at all and if that is the case, then this check will be performed. If the required prop 124 00:10:26,610 --> 00:10:31,620 is not set, this check will not be performed and therefore this validation is not performed and that's 125 00:10:31,620 --> 00:10:33,870 the case for all my different validations here. 126 00:10:34,080 --> 00:10:40,180 So we can set a required prop to check whether it's not empty, if it is empty, we set is valid to false. 127 00:10:40,440 --> 00:10:46,140 We can set an email prop on the input component to validate it for being a valid email address and 128 00:10:46,320 --> 00:10:48,330 if it's not, we set it to false. 129 00:10:48,450 --> 00:10:55,260 We can check a number for being too small or too big or a string for being too short with the min length 130 00:10:55,260 --> 00:10:56,070 validator 131 00:10:56,070 --> 00:11:01,950 and of course you could add more logic here, possibly also with a package like ValidateJs which 132 00:11:01,950 --> 00:11:09,800 I already mentioned earlier. Now with that, I will have is valid in the end which is true by default but 133 00:11:09,940 --> 00:11:16,520 false as soon as one validation fails and therefore now, we can add is valid to this dispatched action 134 00:11:16,520 --> 00:11:17,060 as well.