<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alessio Carnevale</title>
    <description>The latest articles on DEV Community by Alessio Carnevale (@cuginoale).</description>
    <link>https://dev.to/cuginoale</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F164897%2Fb5ad9c99-702b-4c4b-9b9f-1ebf97866b0c.jpeg</url>
      <title>DEV Community: Alessio Carnevale</title>
      <link>https://dev.to/cuginoale</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cuginoale"/>
    <language>en</language>
    <item>
      <title>One Time Password component — an optical illusion?</title>
      <dc:creator>Alessio Carnevale</dc:creator>
      <pubDate>Wed, 31 Aug 2022 14:31:02 +0000</pubDate>
      <link>https://dev.to/cuginoale/one-time-password-component-an-optical-illusion-2n7i</link>
      <guid>https://dev.to/cuginoale/one-time-password-component-an-optical-illusion-2n7i</guid>
      <description>&lt;p&gt;Recently I have been building the login/register section of a web site where, at some point, I had to implement an &lt;strong&gt;OTP&lt;/strong&gt; component to confirm the account creation: a component similar to the one in the screenshot above.&lt;/p&gt;

&lt;p&gt;The first thing I thought when I saw the UI design was: “Ok, I need to create an array of &lt;code&gt;&amp;lt;input/&amp;gt;&lt;/code&gt; elements and then add one or two hundreds of JS lines to handle the internal state, allow the user to enter/edit the code and to handle values pasted from the clip-board.&lt;/p&gt;

&lt;p&gt;But then this question came to me mind: &lt;strong&gt;why?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why do we have to implement such a design and more importantly: &lt;strong&gt;what problem are we trying to solve here?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why do we need to have 6 input boxes and write all the logic to make them behave as if they were just a single input box?&lt;/p&gt;

&lt;p&gt;Functionally speaking all we need to do is to allow the user to type in a 6 character string, yet most (if not all) the implementations of this component I saw on &lt;strong&gt;NPM&lt;/strong&gt; are all basically following the same pattern: an array of input boxes and a lot of &lt;strong&gt;JS&lt;/strong&gt; to make them work together seamlessly.&lt;/p&gt;

&lt;p&gt;It feels wrong, there’s something I am not getting.&lt;/p&gt;




&lt;p&gt;After spending some time with these questions in my head I came up with the following explanation: &lt;strong&gt;it is an optical illusion!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;The origin of that design pattern probably dates back to the times where forms were printed on paper and people had to fill them manually, with a pen in their hand:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9_Binm8v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2AySoMcFckWiYGOBx7sUuy8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9_Binm8v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2AySoMcFckWiYGOBx7sUuy8g.png" alt="" width="474" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having basically no control over the form filling process (we didn’t have client-side validation at that time) we came up with graphical solutions that would help the user to provide the data in a way that was as clear and correct as possible, i.e. in the screenshot above we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  boxes to separate each character&lt;/li&gt;
&lt;li&gt;  pre-formatted date fields to clarify the date format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the example above it is clear that “DATE OF BIRTH” has been broken down to 8 boxes to suggest the user that we need the date to be in the &lt;strong&gt;dd/mm/yyyy&lt;/strong&gt; format rather than &lt;strong&gt;dd/mm/yy.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is just a graphical treatment meant to help the user to fill the form in correctly.&lt;/p&gt;

&lt;p&gt;These days we have electronic forms and those things give us full control over the filling process. We no longer need to split the information into its atomic parts to help the user to provide the correct data… and even if we decide to do so we can do it just at the graphical level.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;OTP component&lt;/strong&gt; is (or should) be just that. From a graphical perspective it looks like a bunch of input-boxes but from a technical perspective it should be implemented as just one.&lt;/p&gt;

&lt;p&gt;Building it as an array of inputs doesn’t solve any issue: on the contrary it requires a lot of effort to make it work and to maintain.&lt;/p&gt;

&lt;p&gt;It is my candidate to the “Worst spent 200 lines of JS” award of the year!&lt;/p&gt;




&lt;p&gt;To get confirmation that the &lt;strong&gt;OTP&lt;/strong&gt; can be a simple text box I looked around and saw that these two big guys have implemented it exactly as a simple input element:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WWQe25Pw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2AAn0yTIpAvOw4dprkksjXHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WWQe25Pw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2AAn0yTIpAvOw4dprkksjXHg.png" alt="" width="486" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QA8KAFfN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2AyMSjCl7H_vEUJyBOKNyS9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QA8KAFfN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2AyMSjCl7H_vEUJyBOKNyS9w.png" alt="" width="362" height="574"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Let’s implement it anyway
&lt;/h3&gt;

&lt;p&gt;So, in case we desperately need to implement a design like the one we saw at the beginning of this article, we can try adding some &lt;strong&gt;CSS&lt;/strong&gt; and a few lines of &lt;strong&gt;Js.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Quick interaction example: &lt;a href="https://youtu.be/iHdUOPLdRCM"&gt;https://youtu.be/iHdUOPLdRCM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A live demo is &lt;a href="https://codesandbox.io/s/onetimepassword-f0y0uk?file=/src/App.tsx"&gt;available in here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In essence, we need to use a &lt;strong&gt;monospaced&lt;/strong&gt; font in our component as this way each character has the same width. This allows us to create and position some &lt;code&gt;&amp;lt;span/&amp;gt;&lt;/code&gt;in the background to give the illusion of multiple input-boxes.&lt;/p&gt;

&lt;p&gt;The code is fairly simple and should be easily customisable by anyone familiar with CSS and JS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final words
&lt;/h3&gt;

&lt;p&gt;I had to write this down and share it with someone: is the &lt;strong&gt;OTP&lt;/strong&gt; an optical illusion or am I hallucinating 🤔 ???&lt;/p&gt;

&lt;p&gt;Your feedback would be highly appreciated!&lt;/p&gt;

</description>
      <category>react</category>
      <category>otp</category>
      <category>2fa</category>
    </item>
    <item>
      <title>Form validation/submission in vanilla React (part 2)</title>
      <dc:creator>Alessio Carnevale</dc:creator>
      <pubDate>Sun, 28 Aug 2022 16:27:00 +0000</pubDate>
      <link>https://dev.to/cuginoale/form-validationsubmission-in-vanilla-react-part-2-3gok</link>
      <guid>https://dev.to/cuginoale/form-validationsubmission-in-vanilla-react-part-2-3gok</guid>
      <description>&lt;h2&gt;
  
  
  A not so trivial example
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/cuginoale/form-validationsubmission-in-vanilla-react-no-libraries-51jm"&gt;first part of this article&lt;/a&gt; I proposed implementing form validation/submission in vanilla React (no 3rd party libraries) using HTML5 and Constraint API.&lt;/p&gt;

&lt;p&gt;The code example provided was intentionally simple to make the point that, if you build the feature on top of the native implementation, then you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  only need to write a fraction of code to handle forms&lt;/li&gt;
&lt;li&gt;  don’t need to learn how to use a new library&lt;/li&gt;
&lt;li&gt;  get a lighter JS bundle&lt;/li&gt;
&lt;li&gt;  reduce the number of dependencies&lt;/li&gt;
&lt;li&gt;you don’t need to write tests for the validation fn, it’s already been tested!&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This time I would like to add a less trivial component to our form: the &lt;strong&gt;password&lt;/strong&gt; field.&lt;/p&gt;

&lt;p&gt;The end product will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2A0Fk14U9-DaD36gqtLH6Iyw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2A0Fk14U9-DaD36gqtLH6Iyw.png" alt="A less trivial example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and the interactive &lt;strong&gt;demo&lt;/strong&gt; is &lt;a href="https://codesandbox.io/s/not-so-simple-form-validation-dj6296?file=/src/App.tsx:944-965" rel="noopener noreferrer"&gt;available here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The password field in our form is responsible for validating the user input, testing it against the following 5 validation rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  mandatory&lt;/li&gt;
&lt;li&gt;  at least one Uppercase&lt;/li&gt;
&lt;li&gt;  at least one digit&lt;/li&gt;
&lt;li&gt;  at least 8 characters&lt;/li&gt;
&lt;li&gt;  at least one special character&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also comes with the show/hide password button to toggle the password visibility.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://codesandbox.io/s/not-so-simple-form-validation-dj6296?file=/src/components/passwordInput.tsx" rel="noopener noreferrer"&gt;password component&lt;/a&gt; is built on top of the &lt;strong&gt;TextInput&lt;/strong&gt; component we already implemented in part one. The only thing I added was the &lt;strong&gt;RhsComponent&lt;/strong&gt; prop to inject the show/hide button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AWHjCL5kV_2DZjHNmwI4AMA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AWHjCL5kV_2DZjHNmwI4AMA.png" alt="Password component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;PlainTextToggle&lt;/strong&gt; is just a button that toggles &lt;strong&gt;isPlainText&lt;/strong&gt; state var between true and false. This in turn switches the input type between “&lt;strong&gt;text&lt;/strong&gt;“ and “&lt;strong&gt;password&lt;/strong&gt;”.  I am not going to discuss this implementation further has it’s not in the scope of this article.&lt;/p&gt;

&lt;p&gt;All the validation magic comes courtesy of the &lt;strong&gt;pattern&lt;/strong&gt; prop!&lt;/p&gt;

&lt;h3&gt;
  
  
  Validating the password
&lt;/h3&gt;

&lt;p&gt;As we know HTML5 allows for custom validation through the use of the &lt;strong&gt;pattern&lt;/strong&gt; property. &lt;strong&gt;Pattern&lt;/strong&gt; needs to be a valid &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions" rel="noopener noreferrer"&gt;RegEx&lt;/a&gt;… or the combination of multiple RegExes.&lt;/p&gt;

&lt;p&gt;I am no expert when it comes to writing regular expressions so I googled around and found the following four (&lt;a href="https://codesandbox.io/s/not-so-simple-form-validation-dj6296?file=/src/utils/validationRules.ts" rel="noopener noreferrer"&gt;utils/validationRules.ts&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AQpiohl5RLtLr-V29cyAJdQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AQpiohl5RLtLr-V29cyAJdQ.png" alt="Regular expressions magic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first four lines in the above screenshot implement 4 of our requirements. The &lt;strong&gt;PASSWORD_VALID_REGEX&lt;/strong&gt; further down is the combination (in logical AND) of the those four RegExes and that is what we are going to set in the password pattern property.&lt;/p&gt;

&lt;p&gt;Please note that the &lt;strong&gt;password&lt;/strong&gt; component is just this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AFbClc8Rn2alqo66Lf5nsfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AFbClc8Rn2alqo66Lf5nsfg.png" alt="The password component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and, as we said, it’s &lt;strong&gt;pattern&lt;/strong&gt; attribute is &lt;strong&gt;PASSWORD_VALID_REGEX&lt;/strong&gt; i.e. the string that combines the 4 RegExes.&lt;/p&gt;

&lt;p&gt;The fifth validation rule, &lt;strong&gt;required&lt;/strong&gt;, is enforced by the “required” HTML attribute as we already saw when we implemented the &lt;strong&gt;name&lt;/strong&gt; and &lt;strong&gt;email&lt;/strong&gt; fields.&lt;/p&gt;

&lt;p&gt;This code alone already implements all of our requirements!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let me repeat this again: to implement all of the 5 validation rules we just need to provide one string and one attribute!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is all this component needs to do: to get the user input and validate it against the pattern that comes out of the composition of 4 simple regular expressions. No more, no less than what the &lt;strong&gt;Tel&lt;/strong&gt; field does in our form.&lt;/p&gt;

&lt;p&gt;If it wasn’t for the show/hide toggle component then the &lt;strong&gt;password&lt;/strong&gt; component code would have looked like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AFABmvKviccp30uMc1Bwe7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AFABmvKviccp30uMc1Bwe7w.png" alt="shorter code"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Check list
&lt;/h3&gt;

&lt;p&gt;To improve the UX and provide visual feedback of the validation process we are now going to add the &lt;a href="https://codesandbox.io/s/not-so-simple-form-validation-dj6296?file=/src/components/checklist.tsx" rel="noopener noreferrer"&gt;&lt;strong&gt;CheckList&lt;/strong&gt; component&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AjiBaiS_oT7hJeb_dGJtyFw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AjiBaiS_oT7hJeb_dGJtyFw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It gets the password the user types in and runs it through the four RegExes to check which one is satisfied.&lt;/p&gt;

&lt;p&gt;We start defining an array &lt;em&gt;(rules)&lt;/em&gt; that gets mapped to an array of &lt;strong&gt;&lt;em&gt;&lt;/em&gt;&lt;/strong&gt; tags. If the pattern is matched then we add the &lt;strong&gt;“passed”&lt;/strong&gt; className to tweak the style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2A0y823sdRYvREFS44AR8FCA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2A0y823sdRYvREFS44AR8FCA.png"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Composing them
&lt;/h3&gt;

&lt;p&gt;Next step is to compose the &lt;strong&gt;PasswordInput&lt;/strong&gt; and the &lt;strong&gt;CheckList&lt;/strong&gt; components. We do this in the &lt;strong&gt;PasswordWithChecklist:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AC8SBT5bJ1JPLifQcwfOdcg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AC8SBT5bJ1JPLifQcwfOdcg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It simply funnels the password value it gets from &lt;strong&gt;PasswordInput&lt;/strong&gt; into &lt;strong&gt;CheckList.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  In the end
&lt;/h3&gt;

&lt;p&gt;Our &lt;strong&gt;App.tsx&lt;/strong&gt; now looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AurjX2DZ48Bh53ZnioSyRaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AurjX2DZ48Bh53ZnioSyRaw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just one line taller than the one we have in &lt;a href="https://dev.to/cuginoale/form-validationsubmission-in-vanilla-react-no-libraries-51jm"&gt;part-one&lt;/a&gt; :)&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>react</category>
      <category>html</category>
      <category>form</category>
      <category>validation</category>
    </item>
    <item>
      <title>Form validation/submission in vanilla React (no libraries)</title>
      <dc:creator>Alessio Carnevale</dc:creator>
      <pubDate>Tue, 23 Aug 2022 16:00:18 +0000</pubDate>
      <link>https://dev.to/cuginoale/form-validationsubmission-in-vanilla-react-no-libraries-51jm</link>
      <guid>https://dev.to/cuginoale/form-validationsubmission-in-vanilla-react-no-libraries-51jm</guid>
      <description>&lt;h1&gt;
  
  
  Form validation/submission in vanilla React (no libraries)
&lt;/h1&gt;

&lt;p&gt;You don’t need a fancy library when you have HTML5 and Constraint API.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Link to part-two: &lt;a href="https://dev.to/cuginoale/form-validationsubmission-in-vanilla-react-part-2-3gok"&gt;a not so trivial example&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;The official  &lt;strong&gt;React&lt;/strong&gt;  documentation suggests 3 possible ways to handle form submission/validation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Controlled components&lt;/li&gt;
&lt;li&gt;  Uncontrolled components&lt;/li&gt;
&lt;li&gt;  Fully-fledged solutions (3rd party libs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But none of these 3 methods are particularly appealing to me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Controlled components&lt;/strong&gt;: I personally don’t like controlled components as it involves manual state management that, most of the times, leads to unneeded and inefficient re-renderings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Uncontrolled components&lt;/strong&gt;: React docs suggests implementing uncontrolled components using a  &lt;a href="https://reactjs.org/docs/refs-and-the-dom.html" rel="noopener noreferrer"&gt;ref&lt;/a&gt;  to get form values from the DOM but then doesn’t provide much info on what the best practises are to extract the data and validate it.&lt;/p&gt;

&lt;p&gt;Either way, we are left with the non trivial task of implementing the logic to validate and collect the form data.&lt;/p&gt;

&lt;p&gt;These days there are  &lt;a href="https://blog.logrocket.com/react-form-validation-sollutions-ultimate-roundup/" rel="noopener noreferrer"&gt;plenty of  &lt;strong&gt;3rd party libraries&lt;/strong&gt;&lt;/a&gt;  that do exactly that... but do we really need one?&lt;/p&gt;




&lt;h1&gt;
  
  
  The goal
&lt;/h1&gt;

&lt;p&gt;Let’s build a simple form like this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F355%2F1%2A83CPpXFjyhuL96r-Rtt9dg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F355%2F1%2A83CPpXFjyhuL96r-Rtt9dg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Interactive&lt;/em&gt; &lt;a href="https://ghxg1m.csb.app/" rel="noopener noreferrer"&gt;&lt;em&gt;demo available here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We want to build a form implementing the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Name&lt;/strong&gt;  and  &lt;strong&gt;Email&lt;/strong&gt;  are mandatory&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Email&lt;/strong&gt;  should represent a valid email address&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Address&lt;/strong&gt;  is optional, no constraints&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Tel&lt;/strong&gt;  is optional but if entered it should represent a formally correct UK phone number&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On submit the form gets validated and should show validation errors like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F355%2F1%2A79jb5OUbFtXM8gYoxb38kg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F355%2F1%2A79jb5OUbFtXM8gYoxb38kg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In case of validation errors the focus should be moved to the first invalid field.&lt;/p&gt;




&lt;h1&gt;
  
  
  HTML5 and Constraint API
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;(Source&lt;/em&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation#using_built-in_form_validation" rel="noopener noreferrer"&gt;&lt;em&gt;MDN&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;: HTML5 already has the ability to validate most user data without relying on JavaScript. This is done by using  &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation#using_built-in_form_validation" rel="noopener noreferrer"&gt;validation attributes on form elements&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required" rel="noopener noreferrer"&gt;required&lt;/a&gt;: Specifies whether a form field needs to be filled in before the form can be submitted.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/minlength" rel="noopener noreferrer"&gt;minlength&lt;/a&gt;  and  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/maxlength" rel="noopener noreferrer"&gt;maxlength&lt;/a&gt;: Specifies the minimum and maximum length of textual data (strings).&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/min" rel="noopener noreferrer"&gt;min&lt;/a&gt;  and  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/max" rel="noopener noreferrer"&gt;max&lt;/a&gt;: Specifies the minimum and maximum values of numerical input types.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;type&lt;/code&gt;: Specifies whether the data needs to be a number, an email address, or some other specific preset type.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern" rel="noopener noreferrer"&gt;pattern&lt;/a&gt;: Specifies a  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions" rel="noopener noreferrer"&gt;regular expression&lt;/a&gt;  that defines a pattern the entered data needs to follow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the data entered in a form field follows all of the rules specified by the above attributes, it is considered valid. If not, it is considered invalid.&lt;/p&gt;

&lt;p&gt;Most browsers support the  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Constraint_validation" rel="noopener noreferrer"&gt;Constraint Validation API&lt;/a&gt;, which consists of a set of methods and properties that enable checking values that users have entered into form controls, before submitting the values to the server.&lt;/p&gt;

&lt;p&gt;With these tools at our disposal we can build custom components for easy and efficient form management.&lt;/p&gt;




&lt;h1&gt;
  
  
  The solution
&lt;/h1&gt;

&lt;p&gt;The building blocks of our solution are the following two custom components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;&amp;lt;Form /&amp;gt;&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;&amp;lt;TextInput /&amp;gt;&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;&amp;lt;Form /&amp;gt;&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F528%2F1%2AM-W6FMCbeE151xwVEJF5cw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F528%2F1%2AM-W6FMCbeE151xwVEJF5cw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key attribute here is  &lt;strong&gt;noValidate.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/novalidate" rel="noopener noreferrer"&gt;novalidate&lt;/a&gt;  attribute turns off the browser's automatic validation error messages. Without that our form would look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F379%2F1%2AJ95osu37vPxJcB98DBYvZQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F379%2F1%2AJ95osu37vPxJcB98DBYvZQ.png" alt="default validation feedback"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the magic happens in the  &lt;strong&gt;handleSubmit&lt;/strong&gt; callback:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F628%2F1%2ABEtmEWqdGK3keWfuVDpHCQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F628%2F1%2ABEtmEWqdGK3keWfuVDpHCQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  we stop the form submission with  &lt;strong&gt;e.preventDefault()&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  we make a note of the form validity state with  &lt;strong&gt;isValid&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  we add the “submitted” className to improve the UX (more on this in a moment)&lt;/li&gt;
&lt;li&gt;  we move the focus to the first invalid field, if any&lt;/li&gt;
&lt;li&gt;  we collect the form data and call the  &lt;strong&gt;onSubmit&lt;/strong&gt;  callback, if valid&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last one is another key point of this solution: collecting the form data using the  &lt;strong&gt;FormData&lt;/strong&gt;  object. There is no need to manually go through the form elements and extract their values.&lt;/p&gt;

&lt;p&gt;“The  &lt;code&gt;FormData&lt;/code&gt;  interface provides a way to easily construct a set of key/value pairs representing form fields and their values” —(  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData" rel="noopener noreferrer"&gt;&lt;em&gt;source: MDN&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;&amp;lt;TextInput /&amp;gt;&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;The TextInput component is responsible for rendering the input field, the label and the possible validation error.&lt;/p&gt;

&lt;p&gt;You can see the  &lt;a href="https://codesandbox.io/s/simple-form-validation-ghxg1m?file=/src/components/textInput.tsx" rel="noopener noreferrer"&gt;code here&lt;/a&gt;, but essentially this component sets an internal state variable with the validation error string coming from the constraint API and resets it on blur if the error has been fixed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F526%2F1%2AZxSlDwNLcDUcccTlnaprXQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F526%2F1%2AZxSlDwNLcDUcccTlnaprXQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;

&lt;p&gt;The code to implement the form in the example looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2A8YmgnL-tBrs6TkWyp_jlRg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2A8YmgnL-tBrs6TkWyp_jlRg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Things to notice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We set the  &lt;strong&gt;required&lt;/strong&gt;  attribute on  &lt;strong&gt;Name&lt;/strong&gt;  and  &lt;strong&gt;Email&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;type=”email”&lt;/strong&gt;  makes sure Constraint API checks the input is a valid email address&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Address&lt;/strong&gt;  as no validation rules&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Tel&lt;/strong&gt;  is not  &lt;strong&gt;required&lt;/strong&gt;  but we set the  &lt;strong&gt;pattern&lt;/strong&gt;  attribute to check the input against the regex (setting  &lt;strong&gt;type=tel&lt;/strong&gt;  doesn’t enforce any  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/tel" rel="noopener noreferrer"&gt;built in validation&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whenever we need to add another field to the form we just add a new  &lt;strong&gt;TextInput&lt;/strong&gt;  and we set the relevant attributes to it.&lt;/p&gt;

&lt;p&gt;No need to update schemas or add yet another  &lt;strong&gt;useState&lt;/strong&gt;  to track the value of the new field, lets just offload the heavy lifting to the built-in API!&lt;/p&gt;

&lt;h1&gt;
  
  
  Improving the UX
&lt;/h1&gt;

&lt;p&gt;The final touch to improve the UX is to show validation errors only after the form gets submitted.&lt;/p&gt;

&lt;p&gt;Using just the  &lt;strong&gt;:invalid&lt;/strong&gt;  pseudo class in our CSS to style incorrect fields would cause red highlighted input boxes and error messages to appear as soon as the page loads… and we don’t want to scream in the face of a user that his/her input is incorrect before they even have the chance to type a character in!&lt;/p&gt;

&lt;p&gt;For this reason we add the  &lt;strong&gt;.submitted&lt;/strong&gt;  className to the form and style the TextInput with this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F341%2F1%2AO6l2jRb-OSEDNGnfrKgWtg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F341%2F1%2AO6l2jRb-OSEDNGnfrKgWtg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  i18n
&lt;/h1&gt;

&lt;p&gt;One great thing to keep in mind is that the constraint API validation messages are localised by default — i.e. they come in the locale the user OS is set to!&lt;/p&gt;

&lt;p&gt;If you are happy with the default messages then there is nothing else you need to worry about: your English, Spanish, Italian or Chinese users will get the messages in their own language.&lt;/p&gt;

&lt;p&gt;The  &lt;strong&gt;TextInput&lt;/strong&gt;  component provided in the example allows also for basic validation message customisation via the  &lt;strong&gt;errorText&lt;/strong&gt; attribute:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F596%2F1%2AZ-XfopKaoLTvEASg_EEI2Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F596%2F1%2AZ-XfopKaoLTvEASg_EEI2Q.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is just an example to show how one could customise those messages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F308%2F1%2Ay2ZBh26eDDPxhNkaBdzlcg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F308%2F1%2Ay2ZBh26eDDPxhNkaBdzlcg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Finally
&lt;/h1&gt;

&lt;p&gt;Once the form is formally correct we can actually submit the from in the  &lt;strong&gt;onSubmit&lt;/strong&gt;  callback.&lt;/p&gt;

&lt;p&gt;We receive a  &lt;strong&gt;FormData&lt;/strong&gt;  object which can then be easily sent using the  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/fetch" rel="noopener noreferrer"&gt;fetch()&lt;/a&gt;  or  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send" rel="noopener noreferrer"&gt;XMLHttpRequest.send()&lt;/a&gt;  method. It uses the same format a form would use if the encoding type were set to  &lt;code&gt;"multipart/form-data"&lt;/code&gt;  , or we can transform it in more familiar key/value object:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F504%2F1%2AkPCl15rJ-u-JMtimxheqHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F504%2F1%2AkPCl15rJ-u-JMtimxheqHg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;to produce the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F487%2F1%2A-0U1nHRwfFJC2M4ki0HV3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F487%2F1%2A-0U1nHRwfFJC2M4ki0HV3w.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Final words
&lt;/h1&gt;

&lt;p&gt;There is beauty in simplicity and form validation/submission doesn’t get much simpler than this IMHO 🙂&lt;/p&gt;

&lt;p&gt;Any comment / feedback is much appreciated!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Link to part-two: &lt;a href="https://dev.to/cuginoale/form-validationsubmission-in-vanilla-react-part-2-3gok"&gt;a not so trivial example&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>html</category>
      <category>form</category>
      <category>validation</category>
    </item>
  </channel>
</rss>
