{"id":12751,"date":"2024-11-03T14:28:25","date_gmt":"2024-11-03T14:28:25","guid":{"rendered":"https:\/\/codevoweb.com\/?p=12751"},"modified":"2024-11-03T14:31:27","modified_gmt":"2024-11-03T14:31:27","slug":"how-to-validate-react-js-forms-without-external-libraries","status":"publish","type":"post","link":"https:\/\/codevoweb.com\/how-to-validate-react-js-forms-without-external-libraries\/","title":{"rendered":"How to Validate React.js Forms Without External Libraries"},"content":{"rendered":"\n<p>In this article, you will learn how to validate React.js forms without relying on external libraries. Good form validation can make the difference between a positive user experience and a negative one. <\/p>\n\n\n\n<p>Therefore, we will not only handle the validation process, but I will also provide tips that you can use to enhance validation in your forms.<\/p>\n\n\n\n<p>More practice<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/setup-and-use-nextauth-in-nextjs-14-app-directory\/\">Setup and Use NextAuth.js in Next.js 14 App Directory<\/a><\/li>\n\n\n\n<li><a href=\"\/implement-authentication-with-nextauth-in-nextjs-14\/\">Implement Authentication with NextAuth in Next.js 14<\/a><\/li>\n\n\n\n<li><a href=\"\/google-and-github-oauth-with-nextauth-in-nextjs-14\/\">Set up Google and GitHub OAuth with NextAuth in Next.js 14<\/a><\/li>\n\n\n\n<li><a href=\"\/implement-authentication-with-supabase-in-nextjs-14\/\">Implement Authentication with Supabase in Next.js 14<\/a><\/li>\n\n\n\n<li><a href=\"\/setup-google-github-oauth-with-supabase-in-nextjs-14\/\">Setup Google and GitHub OAuth with Supabase in Next.js 14<\/a><\/li>\n\n\n\n<li><a href=\"\/implement-authentication-with-trpc-in-nextjs-14\/\">Implement Authentication with tRPC in Next.js 14<\/a><\/li>\n\n\n\n<li><a href=\"\/implement-authentication-with-trpc-api-in-nextjs-14\/\">Implement Authentication with tRPC API in Next.js 14<\/a><\/li>\n\n\n\n<li><a href=\"\/using-trpc-with-nextjs-14-react-query-and-prisma\/\">Using tRPC with Next.js 14, React Query and Prisma<\/a><\/li>\n\n\n\n<li><a href=\"\/how-to-set-up-and-use-react-query-in-next-js-14\/\">How to Set Up and Use React Query in Next.js 14<\/a><\/li>\n\n\n\n<li><a href=\"\/using-react-query-with-supabase-in-next-js-app-router\/\">Using React Query with Supabase in Next.js App Router<\/a><\/li>\n\n\n\n<li><a href=\"\/setup-react-query-in-nextjs-13-app-directory\/\">How to Setup React Query in Next.js 13 App Directory<\/a><\/li>\n\n\n\n<li><a href=\"\/react-query-user-registration-and-email-verification\">React Query and Axios: User Registration and Email Verification<\/a><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"850\" height=\"552\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/How-to-Validate-React.js-Forms-Without-External-Libraries.webp\" alt=\"How to Validate React.js Forms Without External Libraries\" class=\"wp-image-12776\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/How-to-Validate-React.js-Forms-Without-External-Libraries.webp 850w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/How-to-Validate-React.js-Forms-Without-External-Libraries-300x195.webp 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/How-to-Validate-React.js-Forms-Without-External-Libraries-768x499.webp 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/How-to-Validate-React.js-Forms-Without-External-Libraries-100x65.webp 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/How-to-Validate-React.js-Forms-Without-External-Libraries-693x450.webp 693w\" sizes=\"auto, (max-width: 850px) 100vw, 850px\" \/><\/figure>\n\n\n<style>.kb-table-of-content-nav.kb-table-of-content-id12751_07fe99-a6 .kb-table-of-content-wrap{padding-top:var(--global-kb-spacing-sm, 1.5rem);padding-right:var(--global-kb-spacing-sm, 1.5rem);padding-bottom:var(--global-kb-spacing-sm, 1.5rem);padding-left:var(--global-kb-spacing-sm, 1.5rem);border-top:1px solid #abb8c3;border-right:1px solid #abb8c3;border-bottom:1px solid #abb8c3;border-left:1px solid #abb8c3;}.kb-table-of-content-nav.kb-table-of-content-id12751_07fe99-a6 .kb-table-of-contents-title-wrap{padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;}.kb-table-of-content-nav.kb-table-of-content-id12751_07fe99-a6 .kb-table-of-contents-title-wrap{color:#ffffff;}.kb-table-of-content-nav.kb-table-of-content-id12751_07fe99-a6 .kb-table-of-contents-title{color:#ffffff;font-weight:regular;font-style:normal;}.kb-table-of-content-nav.kb-table-of-content-id12751_07fe99-a6 .kb-table-of-content-wrap .kb-table-of-content-list{color:#ffffff;font-weight:regular;font-style:normal;margin-top:var(--global-kb-spacing-sm, 1.5rem);margin-right:0px;margin-bottom:0px;margin-left:0px;}@media all and (max-width: 1024px){.kb-table-of-content-nav.kb-table-of-content-id12751_07fe99-a6 .kb-table-of-content-wrap{border-top:1px solid #abb8c3;border-right:1px solid #abb8c3;border-bottom:1px solid #abb8c3;border-left:1px solid #abb8c3;}}@media all and (max-width: 767px){.kb-table-of-content-nav.kb-table-of-content-id12751_07fe99-a6 .kb-table-of-content-wrap{border-top:1px solid #abb8c3;border-right:1px solid #abb8c3;border-bottom:1px solid #abb8c3;border-left:1px solid #abb8c3;}}<\/style>\n\n\n<h2 class=\"wp-block-heading\">Must-Know Tips for Effective Form Validation<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Choose the Appropriate HTML Input Types<\/strong> &#8211; Ensure you\u2019re using the appropriate input types (e.g., <code>email<\/code>, <code>number<\/code>, <code>password<\/code>) to take advantage of built-in browser validation.<\/li>\n\n\n\n<li><strong>Leverage HTML\u2019s Built-in Validation Properties<\/strong> &#8211; Take advantage of HTML\u2019s native validation attributes, such as <code>required<\/code>, <code>minlength<\/code>, <code>maxlength<\/code>, and <code>pattern<\/code>, to enforce basic rules without needing extra JavaScript or libraries.<\/li>\n\n\n\n<li><strong>Define Custom Tooltips for Built-in Validators<\/strong> \u2013 Customize tooltip messages to guide users when validation errors occur. This can be achieved by using the <code>title<\/code> attribute on the input element.<\/li>\n\n\n\n<li><strong>Provide Specific Validation Messages<\/strong> &#8211; Use clear and informative messages to guide users through correcting input errors.<\/li>\n\n\n\n<li><strong>Pattern Matching with Regex<\/strong> \u2013 For custom formats, apply regular expressions to validate complex patterns, like phone numbers or postal codes.<\/li>\n\n\n\n<li><strong>Highlight Invalid Inputs<\/strong> \u2013 Make it easy for users to see what needs attention by visually highlighting fields with invalid input.<\/li>\n\n\n\n<li><strong>Hide Error Messages When Input is Valid<\/strong> &#8211; Ensure error messages disappear once the input meets validation requirements.<\/li>\n\n\n\n<li><strong>Include Validation on the Server Side<\/strong> \u2013 Enhance security and reliability by validating form data on the server, even after client-side validation.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Run and Test the Validation<\/h2>\n\n\n\n<p>To test the project on your computer, simply follow the instructions below:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>To get started, download or clone the project from its GitHub repository at <a href=\"https:\/\/github.com\/wpcodevo\/form-validation\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/wpcodevo\/form-validation<\/a>.<\/li>\n\n\n\n<li>Navigate to the <code>validate-reactjs-form-no-library<\/code> directory and open the source code in your preferred code editor or IDE.<\/li>\n\n\n\n<li>Open the integrated terminal in your IDE and run the command <code>pnpm install<\/code> to install the necessary dependencies.<\/li>\n\n\n\n<li>After the dependencies have been installed, start the Vite development server by executing the command <code>pnpm dev --port 3000<\/code>.<\/li>\n\n\n\n<li>Finally, open your browser and access the application to test the validation logic.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Overview of the Form Validation <\/h2>\n\n\n\n<p>We will implement form validation in React.js without relying on external validation libraries. This form will consist of multiple fields, each with its specific validation error message that will be displayed when invalid data is entered.<\/p>\n\n\n\n<p>Below is an overview of the fields and their corresponding validation errors.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Username<\/code> &#8211; Username must be at least 3 characters long and can contain letters, numbers, and underscores.<\/li>\n\n\n\n<li><code>Email<\/code> &#8211; Please enter a valid email address.<\/li>\n\n\n\n<li><code>Date Of Birth<\/code> &#8211; Please enter a valid date.<\/li>\n\n\n\n<li><code>Password<\/code> &#8211; Password must be at least 8 characters long, and contain at least one uppercase letter, one lowercase letter, one number, and one special character.<\/li>\n\n\n\n<li><code>Confirm Password<\/code> &#8211; Passwords must match.<\/li>\n<\/ul>\n\n\n\n<p>Validation errors for each input will only be displayed when the user unfocuses the field, provided the entered data does not match the required format. Below is an example illustrating the validation errors for all the input fields.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"810\" height=\"896\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/validation-errors-shown-on-the-form-built-with-React.js-and-no-external-libraries-involved.webp\" alt=\"validation errors shown on the form built with React.js and no external libraries involved\" class=\"wp-image-12765\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/validation-errors-shown-on-the-form-built-with-React.js-and-no-external-libraries-involved.webp 810w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/validation-errors-shown-on-the-form-built-with-React.js-and-no-external-libraries-involved-271x300.webp 271w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/validation-errors-shown-on-the-form-built-with-React.js-and-no-external-libraries-involved-768x850.webp 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/validation-errors-shown-on-the-form-built-with-React.js-and-no-external-libraries-involved-90x100.webp 90w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/validation-errors-shown-on-the-form-built-with-React.js-and-no-external-libraries-involved-407x450.webp 407w\" sizes=\"auto, (max-width: 810px) 100vw, 810px\" \/><\/figure>\n\n\n\n<p>Fields that meet the required format will not display validation errors, as illustrated in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"802\" height=\"827\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/some-fields-are-invalid-while-others-are-valid.webp\" alt=\"some fields are invalid while others are valid\" class=\"wp-image-12766\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/some-fields-are-invalid-while-others-are-valid.webp 802w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/some-fields-are-invalid-while-others-are-valid-291x300.webp 291w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/some-fields-are-invalid-while-others-are-valid-768x792.webp 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/some-fields-are-invalid-while-others-are-valid-97x100.webp 97w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/some-fields-are-invalid-while-others-are-valid-436x450.webp 436w\" sizes=\"auto, (max-width: 802px) 100vw, 802px\" \/><\/figure>\n\n\n\n<p>When the data entered into the input fields is valid, there won&#8217;t be any validation errors, as shown in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"788\" height=\"762\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/create-the-form-and-style-it-with-css.webp\" alt=\"create the form and style it with css\" class=\"wp-image-12767\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/create-the-form-and-style-it-with-css.webp 788w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/create-the-form-and-style-it-with-css-300x290.webp 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/create-the-form-and-style-it-with-css-768x743.webp 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/create-the-form-and-style-it-with-css-100x97.webp 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2024\/11\/create-the-form-and-style-it-with-css-465x450.webp 465w\" sizes=\"auto, (max-width: 788px) 100vw, 788px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the Form Input React Component<\/h2>\n\n\n\n<p>Let\u2019s begin by creating a reusable input component. To make it more versatile, we\u2019ll use <code>React.forwardRef<\/code> to forward its ref to the underlying input element. This will allow parent components to directly access the input DOM element.<\/p>\n\n\n\n<p><strong>components\/form-input.tsx<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-tsx\"><code>\nimport React, { useState } from 'react';\n\nexport interface InputProps\n  extends React.InputHTMLAttributes&lt;HTMLInputElement&gt; {\n  error?: string;\n  label?: string;\n}\n\nconst FormInput = React.forwardRef&lt;HTMLInputElement, InputProps&gt;(\n  ({ type = 'text', name, label, error, className, ...props }, ref) =&gt; {\n    const [focused, setFocus] = useState(false);\n    const handleFocus = () =&gt; {\n      setFocus(true);\n    };\n    return (\n      &lt;div className={`form-input ${className}`}&gt;\n        {label &amp;&amp; &lt;label htmlFor={name}&gt;{label}&lt;\/label&gt;}\n        &lt;input\n          ref={ref}\n          type={type}\n          name={name}\n          className={`input ${error ? 'input-error' : ''} ${\n            focused ? 'input-focused' : ''\n          }`}\n          onFocus={() =&gt; name === 'confirmPassword' &amp;&amp; setFocus(true)}\n          onBlur={handleFocus}\n          {...props}\n        \/&gt;\n        {error &amp;&amp; &lt;span className='error-message'&gt;{error}&lt;\/span&gt;}\n      &lt;\/div&gt;\n    );\n  }\n);\n\nFormInput.displayName = 'FormInput';\n\nexport { FormInput };\n<\/code>\n<\/pre>\n\n\n\n<p>We defined a <code>focus<\/code> state and created a function called <code>handleFocus<\/code> to set this state to <code>true<\/code>. Then, we assigned <code>handleFocus<\/code> to the <code>onBlur<\/code> attribute of the input element.<\/p>\n\n\n\n<p>In React, the <code>onBlur<\/code> event is triggered when an input field loses focus, meaning the user clicks or tabs out of it. Here, <code>onBlur<\/code> helps manage the focus state, which is used to show or hide error messages accordingly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the Form in React<\/h2>\n\n\n\n<p>Now that we\u2019ve defined the input component, let\u2019s use it to render the various input elements in the form. To reduce redundancy and improve code readability, we\u2019ll define each input\u2019s attributes in an array of objects, then map through them to render each input using our reusable component. Below is an example demonstrating this approach.<\/p>\n\n\n\n<p><strong>src\/App.tsx<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-tsx\"><code>\nimport '.\/App.css';\nimport { FormInput } from '..\/components\/form-input';\n\ntype FormValues = {\n  username: string;\n  email: string;\n  dateOfBirth: string;\n  password: string;\n  confirmPassword: string;\n};\n\ntype InputFieldData = {\n  id: number;\n  type: string;\n  name: keyof FormValues;\n  placeholder: string;\n  label: string;\n};\n\nconst inputFieldData: InputFieldData[] = [\n  {\n    id: 1,\n    type: 'text',\n    name: 'username',\n    placeholder: 'Username',\n    label: 'Username',\n  },\n  {\n    id: 2,\n    type: 'email',\n    name: 'email',\n    placeholder: 'Email',\n    label: 'Email',\n  },\n  {\n    id: 3,\n    type: 'date',\n    name: 'dateOfBirth',\n    placeholder: 'Date Of Birth',\n    label: 'Date Of Birth',\n  },\n  {\n    id: 4,\n    type: 'password',\n    name: 'password',\n    placeholder: 'Password',\n    label: 'Password',\n  },\n  {\n    id: 5,\n    type: 'password',\n    name: 'confirmPassword',\n    placeholder: 'Confirm Password',\n    label: 'Confirm Password',\n  },\n];\n\nfunction App() {\n  return (\n    &lt;div className='wrapper'&gt;\n      &lt;form&gt;\n        {inputFieldData.map(({ id, name, ...props }) =&gt; {\n          return &lt;FormInput key={id} name={name} {...props} \/&gt;;\n        })}\n        &lt;button type='submit'&gt;Register Account&lt;\/button&gt;\n      &lt;\/form&gt;\n    &lt;\/div&gt;\n  );\n}\n\nexport default App;\n<\/code>\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Styling the Form with CSS<\/h2>\n\n\n\n<p>Before diving into the validation logic, let\u2019s start by styling the form and adding a background image to enhance its appearance. If you&#8217;re following along, add the following CSS to the <code>src\/App.css<\/code> file.<\/p>\n\n\n\n<p><strong>src\/App.css<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-css\"><code>\n* {\n  box-sizing: border-box;\n}\n\n:root {\n  --primary-color: #007bff;\n  --primary-color-hover: #0056b3;\n  --border-color: #ccc;\n  --error-color: #ff0000;\n  --font-family: Arial, sans-serif;\n}\n\nbody {\n  margin: 0;\n  font-family: var(--font-family);\n  background-image: url('bg.jpg');\n  background-size: cover;\n  background-position: center;\n  color: #333;\n}\n\n.wrapper {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  height: 100vh;\n  max-width: 500px;\n  margin: 0 auto;\n}\n\nform {\n  display: flex;\n  flex-direction: column;\n  width: 100%;\n  padding: 20px;\n  background-color: rgba(255, 255, 255, 0.9);\n  border-radius: 8px;\n  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);\n}\n\n.form-input {\n  display: flex;\n  flex-direction: column;\n  margin-bottom: 15px;\n}\n\nlabel {\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\ninput {\n  padding: 10px;\n  border: 1px solid var(--border-color);\n  border-radius: 4px;\n  font-size: 16px;\n  transition: border-color 0.3s ease;\n}\n\ninput:focus {\n  border-color: var(--primary-color);\n  outline: none;\n}\n\n.error-message {\n  color: var(--error-color);\n  font-size: 12px;\n  margin-top: 10px;\n  display: none;\n}\n\ninput:invalid.input-focused {\n  border-color: var(--error-color);\n}\n\ninput:invalid.input-focused ~ span {\n  display: block;\n}\n\nbutton {\n  padding: 10px;\n  background-color: var(--primary-color);\n  color: white;\n  border: none;\n  border-radius: 4px;\n  cursor: pointer;\n  font-size: 16px;\n  transition: background-color 0.3s ease;\n}\n\nbutton:hover {\n  background-color: var(--primary-color-hover);\n}\n\nbutton:focus {\n  outline: 2px solid var(--primary-color);\n}\n\n@media (max-width: 600px) {\n  .wrapper {\n    max-width: 90%;\n  }\n}\n<\/code>\n<\/pre>\n\n\n\n<p>Looking through the CSS, you\u2019ll notice that validation styling is applied directly to the input field. When an input has an invalid value, it checks for the presence of the <code>input-focused<\/code> class. If this class is present, the input\u2019s border colour changes to red, and the error message becomes visible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Writing the Validation Logic<\/h2>\n\n\n\n<p>With the styling for the input elements complete, we can now proceed to implement the validation logic. We\u2019ll leverage HTML5\u2019s <code>pattern<\/code> and <code>required<\/code> attributes to handle validation. In the input data object, add fields for <code>errorMessage<\/code>, <code>required<\/code>, and <code>pattern<\/code>, each with appropriate values. To make this easier, simply copy the code below and replace it with the existing code:<\/p>\n\n\n\n<p><strong>src\/App.tsx<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-tsx\"><code>\nimport '.\/App.css';\nimport { FormInput } from '..\/components\/form-input';\nimport React, { useState } from 'react';\n\ntype FormValues = {\n  username: string;\n  email: string;\n  dateOfBirth: string;\n  password: string;\n  confirmPassword: string;\n};\n\ntype InputFieldData = {\n  id: number;\n  type: string;\n  name: keyof FormValues;\n  placeholder: string;\n  label: string;\n  error: string;\n  pattern?: string;\n  required: boolean;\n};\n\nconst inputFieldData: InputFieldData[] = [\n  {\n    id: 1,\n    type: 'text',\n    name: 'username',\n    placeholder: 'Username',\n    label: 'Username',\n    error:\n      'Username must be at least 3 characters long and can contain letters, numbers, and underscores.',\n    pattern: '^[a-zA-Z0-9_]{3,}$',\n    required: true,\n  },\n  {\n    id: 2,\n    type: 'email',\n    name: 'email',\n    placeholder: 'Email',\n    label: 'Email',\n    error: 'Please enter a valid email address.',\n    pattern: '^[^\\\\s@]+@[^\\\\s@]+\\\\.[^\\\\s@]+$',\n    required: true,\n  },\n  {\n    id: 3,\n    type: 'date',\n    name: 'dateOfBirth',\n    placeholder: 'Date Of Birth',\n    label: 'Date Of Birth',\n    error: 'Please enter a valid date.',\n    pattern: '^\\\\d{4}-\\\\d{2}-\\\\d{2}$',\n    required: true,\n  },\n  {\n    id: 4,\n    type: 'password',\n    name: 'password',\n    placeholder: 'Password',\n    label: 'Password',\n    error:\n      'Password must be at least 8 characters long, and contain at least one uppercase letter, one lowercase letter, one number, and one special character.',\n    pattern: '^(?=.*[A-Z])(?=.*[a-z])(?=.*[\\\\d\\\\W])[A-Za-z\\\\d\\\\W]{8,}$',\n    required: true,\n  },\n  {\n    id: 5,\n    type: 'password',\n    name: 'confirmPassword',\n    placeholder: 'Confirm Password',\n    label: 'Confirm Password',\n    error: 'Passwords must match.',\n    required: true,\n  },\n];\n\nfunction App() {\n  const [values, setValues] = useState&lt;FormValues&gt;({\n    username: '',\n    email: '',\n    dateOfBirth: '',\n    password: '',\n    confirmPassword: '',\n  });\n\n  const handleChange = (e: React.ChangeEvent&lt;HTMLInputElement&gt;) =&gt; {\n    const { name, value } = e.target;\n    setValues((prevValues) =&gt; ({\n      ...prevValues,\n      [name]: value,\n    }));\n  };\n\n  const handleSubmit = (e: React.FormEvent&lt;HTMLFormElement&gt;) =&gt; {\n    e.preventDefault();\n\n    console.log('Form submitted:', values);\n  };\n\n  return (\n    &lt;div className='wrapper'&gt;\n      &lt;form onSubmit={handleSubmit}&gt;\n        {inputFieldData.map(({ id, name, ...props }) =&gt; {\n          const dynamicPattern =\n            name === 'confirmPassword' ? `^${values.password}$` : props.pattern;\n          return (\n            &lt;FormInput\n              key={id}\n              name={name}\n              value={values[name]}\n              onChange={handleChange}\n              pattern={dynamicPattern}\n              {...props}\n            \/&gt;\n          );\n        })}\n        &lt;button type='submit'&gt;Register Account&lt;\/button&gt;\n      &lt;\/form&gt;\n    &lt;\/div&gt;\n  );\n}\n\nexport default App;\n<\/code>\n<\/pre>\n\n\n\n<p>To ensure the password-matching logic functions correctly, we dynamically set the <code>pattern<\/code> attribute of the <code>confirm password<\/code> input to match the value of the password input field.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>As we wrap up this comprehensive guide, you&#8217;ve learned how to implement form validation in React.js using the built-in HTML5 <code>pattern<\/code> and <code>required<\/code> attributes, which means there&#8217;s no need for any advanced validation libraries. However, if you wish to handle more complex client-side validation logic, you will need to incorporate a validation library. <\/p>\n\n\n\n<p>I hope you found this article both informative and enjoyable. If you have any questions or feedback, please don&#8217;t hesitate to leave a comment below. Thank you for reading!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article, you will learn how to validate React.js forms without relying on external libraries. Good form validation can make the difference between a&#8230;<\/p>\n","protected":false},"author":1,"featured_media":12776,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[54],"tags":[56],"class_list":["post-12751","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-react","tag-react"],"acf":[],"_links":{"self":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts\/12751","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/comments?post=12751"}],"version-history":[{"count":15,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts\/12751\/revisions"}],"predecessor-version":[{"id":12891,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts\/12751\/revisions\/12891"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/media\/12776"}],"wp:attachment":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/media?parent=12751"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/categories?post=12751"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/tags?post=12751"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}