Creating a Secure Password Indicator Within a Form using React and Formik
Hey! Just so you know, this article is over 2 years old. Some of the information in it might be outdated, so take it with a grain of salt. I'm not saying it's not worth a read, but don't take everything in it as gospel. If you're curious about something, it never hurts to double-check with a more up-to-date source!
The Final Product
#Getting Started
#Boxes and forms are well… what form the internet.
If you're a front-end or full-stack developer, at some point you may be required to create a registration form to let users sign up for a website.
If you are feeling experimental, we can even make the registration form a bit more spicey than your traditional “Enter email”, “Enter password” and “Confirm password”.
One thing I do want to note before we get started is that although you aren't limited to implementing this form with just React, the article will only cover how to achieve so in React. I'll also be skipping out on diving into the CSS for the form as it's fairly simple, but feel free to dig into the code used if you want to learn more about it.
Right, I'll spare the basic overview of what a signup form is and dive straight into the topic of this article, where we will be creating a secure password registration form.
What Our Form Will Do
#The form will do the following -
- Allow a user to enter an email address for their account
- Allow a user to enter a password for their new account
- We will test the password against a set of rules that we'll specify
- Display the user's password progress on meeting all rules on form interactions
- Provide descriptive errors if the user submits the form before completing the requirements
Sounds like a complex set of features for a front-end developer, even with React. Having a form handle validation, updating state and providing errors all based on the user's input.
Formik
#This is where one of my favourite packages, Formik comes into play.
Formik in a nutshell -
Formik takes care of the repetitive and annoying stuff--keeping track of values/errors/visited fields, orchestrating validation, and handling submission--so you don't have to. This means you spend less time wiring up state and change handlers and more time focusing on your business logic.(Formik 2019)
So without further ado, let us get the base markup into an editor for us to show an interface to our user.
I'll go through each part of the code step by step so don't be put off by the large block of code.
Our App
#Fancy Registration Component
#Complete Snippet
#Component Imports
#Our user registration form kicks off with importing React and the 'useState'hook.
We then import Formik so that we can wrap our form in the event handlers and validation events.
Our final import is of a component we will return to later which is a custom 'Requirements' component. This will be used to feedback to our users when they've met the password requirements we will set.
Cool, imports are done.
Setting Component State
#Next up is setting some state variables.
The 'useState' hook allows us to set conditional state variables which will indicate to our user when they've met our password requirement.
Our 'long'state variable will be either true or false (boolean) and will be switched between the two if the user enters a password eight characters in length or more.
Similar to the 'long' variable, the 'number'variable will be toggled between true or false, the state of this variable will change when the user has at least one number in their password or not.
Building the Registration Form
#Finally, we will build our registration form.
Now that's a lot of code, so we'll be breaking this down into smaller steps following on from an overview of what we've done.
As mentioned, we are using Formik for our event handling, so we will wrap all of our HTML markup in the Formik component and use the Formik props to trigger events based on user interaction.
To start off the Formik component, we set our initial values which will be empty strings.
Validating The Form
#Next, we compose a validation event. This validation event by default gets called when the form triggers an onBlur event, onInput event or onSubmit event. This validation event is where the meat of the article really is.
In this validation event, we have access to the values of the form and is where we will do our checks to see if the password value meets the custom requirements we're asking of the user.
Now before we go into the event itself, I first want to describe the two requirements we are going to ask of the user when setting a password. These two requirements include -
- The password must be at least 8 characters in length
- The password must contain at least 1 numeric character
Back to the form!
To kick off the event, we are passing in the values object to our function, this contains the values of any form fields we've included (email and password).
Now comes the actual validation.
Using a ternary operator, we are asking the form to return a boolean based on whether the length count of the form field 'password'is less than 8 characters long.
You can think of a ternary operator as a single line if/else statement.
If the statement returns true then we know the user hasn't met the requirement and we set the state variable to false.
If the statement returns false, it means the user has entered a password at least 8 characters long and so we set the state variable to true, indicating the user has met our requirement.
We then rinse and repeat this syntax, swapping out the statement to test whether or not the password contains a numeric character. Again, we toggle a state variable depending on the boolean value returned by our test.
Processing Submissions
#Next up we create the logic for processing the form submission.
We start this by creating an empty object for any errors we want to display to the user within our markup later on. If this object has no properties then we won't show any errors to our users.
After creating the errors object, we then check the true/false (boolean) values of our state variables. Where 'long' represents if the password string is 8 characters long and 'number'represents if the password has a numeric value.
If either of these values is false, then the password hasn't met our requirements and we attach a message related to the password error we want to display to our users. The message displayed is “Your password doesn't currently meet the requirements”.
To wrap up our submit event, we check if the errors object has any values.
If the errors object is empty then we can successfully process the user's data. To simulate this we are throwing up an alert box but in production, you'd replace this with the actual processing of a users account creation.
If the errors object isn't empty, we use the Formik function setErrors to… you guessed it, set the errors state for the form!
Finally, we set the submitting state of the form to false.
Phew.
That's all of the processing of the data for the form and its state.
Building Form Fields
#Now we move onto building the fields.
I won't go into too much detail of the basic markup, but I will make a note of the helpful functions Formik gives us for certain elements.
As we have two neighboured children elements (H1 and form) we have to wrap the elements in a React.Fragment, the shorthand syntax is an empty element (<></>).
After our wrapper, and the page title, is the form element.
Formik gives us a handleSubmit function which we pass directly into the forms onSubmit property.
Next thing to note is the input fields.
Normally in React, you are responsible for creating state variables that you'd use for the input values, but again Formik is kind enough to provide an object which contains the values of the initial values we set all the way back at the start of the Formik construction process.
To make use of them, the input field value is set to the object key value of the field you want access to. So our email field will use
value={values.password}`.Pretty cool, right? This is why I love Formik.
To listen out for any changes to the fields and process their new values, we attach a handleChange event that Formik provides to our inputs onChange properties.
We've now got the form with inputs that update the form state, next up is displaying our errors to the user if available.
In our code, we are conditionally checking to see if there are any errors for the field password. If there are then we are rendering a
label'is so that when a user clicks on it, it'll focus on the input it is referencing.Finally, we add a submit
form'so that users can get to our onSubmit event. It submit'thrown on it.The only thing to note here is that we are adding a dynamic disabled state. It's always good practice to prevent a user from submitting a form if it's already in the process of submitting. Otherwise, we could create duplicate accounts or throw unexpected errors. To make this state dynamic we make use of the Formik variables
.So that's everything to do with building the form itself, including our validation and submission logic.
Requirements Component
#Now onto the fun part, I mean the extra fun part of this guide ?
We'll be moving onto our requirements component.
Our requirements component takes in two props, which are our state boolean values, long and number.
In the requirements component, we are also importing and using another component, the requirement component (singular). This nested component takes in 4 props.
- The input field name as a HTML for attribute
- isValid which will accept a boolean value for toggle if the requirement has been met or not
- invalidMessage which is shown when our isValid value is false
- validMessage which is shown when our isValid value is true
As we have two fields, I've included two of these components with references to our long and number state value props that were passed down by the Formik component.
Requirement Component
#Our final component is the Requirement component.
The requirement component is made up of a label which references an input field (password in our case). The CSS classes applied to this element will be dynamic based on the isValue value. The classes are responsible for changing the visual validity state to the end-user.
The component content includes an icon which will change colour depending on if the requirement has been met and a text message which alternates again based on if the requirement has been met.
Conclusion
#So we've built a pretty rad user registration form.
This is only an example of what can be achieved with Formik, some basic validation on the front-end and the use of error message handling, validation visual feedback and more.
Using the logic implemented in this article, you could extend the form to include more fields, or ask of stricter requirements.
Maybe try adding in a requirement that asks the user to include at least one capital letter in their password?
I invite you to build your own example and share it with the world, whether it is for learning, fun or in production and tweet at me with your forms! @whatjackhasmade