{"id":73,"date":"2026-07-04T10:10:45","date_gmt":"2026-07-04T10:10:45","guid":{"rendered":"https:\/\/www.kindsonthegenius.com\/react\/06-react-forms\/"},"modified":"2026-07-04T10:14:12","modified_gmt":"2026-07-04T10:14:12","slug":"06-react-forms","status":"publish","type":"post","link":"https:\/\/www.kindsonthegenius.com\/react\/06-react-forms\/","title":{"rendered":"React Forms \u2014 Controlled Inputs and Validation (React 19+)"},"content":{"rendered":"<p><!-- ktg-updated-banner --><\/p>\n<div class=\"ktg-updated-banner\" style=\"margin:0 0 1.25em;padding:0.75em 1em;background:#fefce8;border-left:4px solid #ca8a04;border-radius:4px;\">\n<p><strong>Updated July 4, 2026.<\/strong> Refreshed for React 19 and current SEO best practices.<\/p>\n<\/div>\n<p><!-- ktg-series-toc --><\/p>\n<nav class=\"ktg-series-toc\" aria-label=\"React tutorial table of contents\" style=\"margin:1.5em 0;padding:1em 1.25em;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;\">\n<h2>Table of Contents<\/h2>\n<p>Follow the React tutorial series in order:<\/p>\n<ol>\n<li><a href=\"https:\/\/www.kindsonthegenius.com\/react\/01-react-introduction\/\">Lesson 1: React Tutorial \u2014 Introduction (2026)<\/a><\/li>\n<li><a href=\"https:\/\/www.kindsonthegenius.com\/react\/02-react-setup\/\">Lesson 2: React Setup \u2014 Create Your First App with Vite<\/a><\/li>\n<li><a href=\"https:\/\/www.kindsonthegenius.com\/react\/03-react-jsx-and-components\/\">Lesson 3: React JSX and Components \u2014 Build Your First UI<\/a><\/li>\n<li><a href=\"https:\/\/www.kindsonthegenius.com\/react\/04-react-state-usestate\/\">Lesson 4: React State and useState \u2014 Interactive UI (React 19+)<\/a><\/li>\n<li><a href=\"https:\/\/www.kindsonthegenius.com\/react\/05-react-useeffect\/\">Lesson 5: React useEffect \u2014 Side Effects and Data Fetching (React 19+)<\/a><\/li>\n<li><strong aria-current=\"page\">Lesson 6: React Forms \u2014 Controlled Inputs and Validation (React 19+)<\/strong><\/li>\n<li><a href=\"https:\/\/www.kindsonthegenius.com\/react\/07-react-router\/\">Lesson 7: React Router \u2014 Multi-Page Navigation (React 19+)<\/a><\/li>\n<li><a href=\"https:\/\/www.kindsonthegenius.com\/react\/\">\u2190 Back to React Tutorial hub<\/a><\/li>\n<\/ol>\n<\/nav>\n<p><!-- ktg-react-modern --><\/p>\n<div class=\"ktg-react-modern\" style=\"margin:1.5em 0;padding:1em;background:#eff6ff;border-left:4px solid #2563eb;border-radius:4px;\">\n<h4>React 19 Notes<\/h4>\n<p>Controlled inputs keep a single source of truth in React state \u2014 ideal for validation and reset. React 19 form actions (Server Actions) shine in Next.js; in Vite SPAs, <code>useState<\/code> remains the standard beginner pattern.<\/p>\n<\/div>\n<p>This lesson teaches <strong>React forms<\/strong> using <strong>controlled components<\/strong> \u2014 inputs whose value is driven by React state. You will handle submit events, validate fields, show error messages, and build a complete signup form.<\/p>\n<p><strong>Prerequisites:<\/strong> Lessons 1\u20135, especially <a href=\"https:\/\/www.kindsonthegenius.com\/react\/04-react-state-usestate\/\">useState<\/a>. <strong>Estimated time:<\/strong> 45\u201355 minutes.<\/p>\n<h4 id=\"controlled-vs-uncontrolled\">1. Controlled vs Uncontrolled Inputs<\/h4>\n<p>A <strong>controlled<\/strong> input stores its value in state and updates via <code>onChange<\/code>:<\/p>\n<pre><code class=\"language-jsx\">const [email, setEmail] = useState('');\n\n&lt;input\n  type=\"email\"\n  value={email}\n  onChange={(e) =&gt; setEmail(e.target.value)}\n\/&gt;\n<\/code><\/pre>\n<p>An <strong>uncontrolled<\/strong> input uses a DOM ref \u2014 fine for simple cases, but controlled inputs are easier to validate and reset in React apps.<\/p>\n<figure style=\"margin:1.5em 0;text-align:center;\"><img decoding=\"async\" src=\"https:\/\/www.kindsonthegenius.com\/react\/wp-content\/uploads\/2026\/07\/06-react-forms-section-1.jpg\" alt=\"React controlled form with validation\" width=\"1200\" height=\"675\" loading=\"lazy\" style=\"max-width:100%;height:auto;border-radius:8px;border:1px solid #dee2e6;\" \/><figcaption style=\"font-size:0.85em;color:#666;margin-top:0.5em;\">Photo by <a href=\"https:\/\/unsplash.com\/@teamnocoloco?utm_source=kindsonthegenius&#038;utm_medium=referral\" rel=\"noopener noreferrer\" target=\"_blank\">Team Nocoloco<\/a> on <a href=\"https:\/\/unsplash.com\/?utm_source=kindsonthegenius&#038;utm_medium=referral\" rel=\"noopener noreferrer\" target=\"_blank\">Unsplash<\/a><\/figcaption><\/figure>\n<h4 id=\"form-state-object\">2. Form State as an Object<\/h4>\n<pre><code class=\"language-jsx\">const [form, setForm] = useState({\n  name: '',\n  email: '',\n  password: '',\n});\n\nfunction handleChange(e) {\n  const { name, value } = e.target;\n  setForm((prev) =&gt; ({ ...prev, [name]: value }));\n}\n<\/code><\/pre>\n<p>Use the <code>name<\/code> attribute on each input to update the correct field without separate handlers.<\/p>\n<figure style=\"margin:1.5em 0;text-align:center;\"><img decoding=\"async\" src=\"https:\/\/www.kindsonthegenius.com\/react\/wp-content\/uploads\/2026\/07\/06-react-forms-section-2.jpg\" alt=\"User filling out a web form\" width=\"1200\" height=\"675\" loading=\"lazy\" style=\"max-width:100%;height:auto;border-radius:8px;border:1px solid #dee2e6;\" \/><figcaption style=\"font-size:0.85em;color:#666;margin-top:0.5em;\">Photo by <a href=\"https:\/\/unsplash.com\/@glenncarstenspeters?utm_source=kindsonthegenius&#038;utm_medium=referral\" rel=\"noopener noreferrer\" target=\"_blank\">Glenn Carstens-Peters<\/a> on <a href=\"https:\/\/unsplash.com\/?utm_source=kindsonthegenius&#038;utm_medium=referral\" rel=\"noopener noreferrer\" target=\"_blank\">Unsplash<\/a><\/figcaption><\/figure>\n<h4 id=\"submit-handler\">3. Handling Submit<\/h4>\n<pre><code class=\"language-jsx\">function handleSubmit(e) {\n  e.preventDefault();\n  console.log('Submitting', form);\n  \/\/ POST to API or update parent state\n}\n\nreturn (\n  &lt;form onSubmit={handleSubmit}&gt;\n    {\/* inputs *\/}\n    &lt;button type=\"submit\"&gt;Sign up&lt;\/button&gt;\n  &lt;\/form&gt;\n);\n<\/code><\/pre>\n<p>Always call <code>e.preventDefault()<\/code> unless you want a full page reload.<\/p>\n<h4 id=\"validation\">4. Simple Validation<\/h4>\n<pre><code class=\"language-jsx\">const [errors, setErrors] = useState({});\n\nfunction validate() {\n  const next = {};\n  if (!form.name.trim()) next.name = 'Name is required';\n  if (!form.email.includes('@')) next.email = 'Valid email required';\n  if (form.password.length &lt; 8) next.password = 'Minimum 8 characters';\n  setErrors(next);\n  return Object.keys(next).length === 0;\n}\n\nfunction handleSubmit(e) {\n  e.preventDefault();\n  if (!validate()) return;\n  \/\/ proceed with valid data\n}\n<\/code><\/pre>\n<p>Show errors next to fields: <code>{errors.email &amp;&amp; &lt;span&gt;{errors.email}&lt;\/span&gt;}<\/code>. For larger apps consider <strong>React Hook Form<\/strong> or <strong>Zod<\/strong> \u2014 out of scope for this beginner <strong>react forms tutorial<\/strong>.<\/p>\n<h4 id=\"complete-signup\">5. Complete Example \u2014 SignupForm<\/h4>\n<pre><code class=\"language-jsx\">import { useState } from 'react';\n\nfunction SignupForm() {\n  const [form, setForm] = useState({ name: '', email: '', password: '' });\n  const [errors, setErrors] = useState({});\n  const [submitted, setSubmitted] = useState(false);\n\n  function handleChange(e) {\n    const { name, value } = e.target;\n    setForm((prev) =&gt; ({ ...prev, [name]: value }));\n  }\n\n  function validate() {\n    const next = {};\n    if (!form.name.trim()) next.name = 'Name is required';\n    if (!form.email.includes('@')) next.email = 'Enter a valid email';\n    if (form.password.length &lt; 8) next.password = 'Use at least 8 characters';\n    setErrors(next);\n    return Object.keys(next).length === 0;\n  }\n\n  function handleSubmit(e) {\n    e.preventDefault();\n    if (!validate()) return;\n    setSubmitted(true);\n  }\n\n  if (submitted) {\n    return &lt;p&gt;Thanks, {form.name}! Check {form.email} to confirm.&lt;\/p&gt;;\n  }\n\n  return (\n    &lt;form onSubmit={handleSubmit} style={{ maxWidth: '360px' }}&gt;\n      &lt;label&gt;\n        Name\n        &lt;input name=\"name\" value={form.name} onChange={handleChange} \/&gt;\n        {errors.name &amp;&amp; &lt;small style={{ color: 'crimson' }}&gt;{errors.name}&lt;\/small&gt;}\n      &lt;\/label&gt;\n      &lt;label&gt;\n        Email\n        &lt;input name=\"email\" type=\"email\" value={form.email} onChange={handleChange} \/&gt;\n        {errors.email &amp;&amp; &lt;small style={{ color: 'crimson' }}&gt;{errors.email}&lt;\/small&gt;}\n      &lt;\/label&gt;\n      &lt;label&gt;\n        Password\n        &lt;input name=\"password\" type=\"password\" value={form.password} onChange={handleChange} \/&gt;\n        {errors.password &amp;&amp; &lt;small style={{ color: 'crimson' }}&gt;{errors.password}&lt;\/small&gt;}\n      &lt;\/label&gt;\n      &lt;button type=\"submit\"&gt;Create account&lt;\/button&gt;\n    &lt;\/form&gt;\n  );\n}\n\nexport default SignupForm;\n<\/code><\/pre>\n<p>Add basic CSS (stack labels with <code>display: block<\/code> and margin) and test invalid submissions to see validation messages.<\/p>\n<h4 id=\"checkbox-select\">6. Checkbox and Select<\/h4>\n<pre><code class=\"language-jsx\">&lt;input\n  type=\"checkbox\"\n  checked={form.agree}\n  onChange={(e) =&gt; setForm((prev) =&gt; ({ ...prev, agree: e.target.checked }))}\n\/&gt;\n\n&lt;select\n  name=\"plan\"\n  value={form.plan}\n  onChange={handleChange}\n&gt;\n  &lt;option value=\"free\"&gt;Free&lt;\/option&gt;\n  &lt;option value=\"pro\"&gt;Pro&lt;\/option&gt;\n&lt;\/select&gt;\n<\/code><\/pre>\n<h4 id=\"next\">7. Next Steps<\/h4>\n<p>Forms capture user input; routing sends users between pages. Next you will add <strong>React Router<\/strong> for multi-page navigation in a single-page app.<\/p>\n<p>Series: <a href=\"https:\/\/www.kindsonthegenius.com\/react\/05-react-useeffect\/\">Lesson 5<\/a> \u00b7 <a href=\"https:\/\/www.kindsonthegenius.com\/react\/07-react-router\/\">Lesson 7 \u2014 React Router<\/a><\/p>\n<h4 id=\"faq\">Frequently Asked Questions<\/h4>\n<p><strong>What is a controlled component in React?<\/strong><br \/>\nA controlled component is an input whose value is stored in React state and updated through <code>onChange<\/code>, giving React full control over the field.<\/p>\n<p><strong>Should I use a form library?<\/strong><br \/>\nFor learning and small forms, plain <code>useState<\/code> is enough. Libraries like React Hook Form reduce re-renders and simplify validation in large apps.<\/p>\n<p><strong>How do I reset a form after submit?<\/strong><br \/>\nCall <code>setForm({ name: '', email: '', password: '' })<\/code> and <code>setErrors({})<\/code> after a successful submit.<\/p>\n<p><!-- ktg-faq-schema --><br \/>\n<script type=\"application\/ld+json\">{\"@context\":\"https:\/\/schema.org\",\"@type\":\"FAQPage\",\"mainEntity\":[{\"@type\":\"Question\",\"name\":\"What is a controlled component in React?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"A controlled component is an input whose value is stored in React state and updated through onChange, giving React full control over the field.\"}},{\"@type\":\"Question\",\"name\":\"Should I use a form library in React?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"For small forms, useState is enough. Libraries like React Hook Form help large apps with validation and fewer re-renders.\"}}]}<\/script><\/p>\n<p><!-- ktg-lesson-nav --><\/p>\n<nav class=\"ktg-lesson-nav\" aria-label=\"Lesson navigation\">\n<p><strong>Previous:<\/strong> <a href=\"https:\/\/www.kindsonthegenius.com\/react\/05-react-useeffect\/\">Lesson 5: React useEffect \u2014 Side Effects and Data Fetching (React 19+)<\/a><\/p>\n<p><strong>Next:<\/strong> <a href=\"https:\/\/www.kindsonthegenius.com\/react\/07-react-router\/\">Lesson 7: React Router \u2014 Multi-Page Navigation (React 19+)<\/a><\/p>\n<\/nav>\n<p><!-- ktg-alkademy-cta --><\/p>\n<div class=\"ktg-alkademy-cta\">\n<p><strong>Want live React or frontend classes?<\/strong> Join <a href=\"https:\/\/www.alkademy.com\/courses\" target=\"_blank\" rel=\"noopener noreferrer\">Alkademy<\/a> for instructor-led React and JavaScript courses with hands-on projects.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Updated July 4, 2026. Refreshed for React 19 and current SEO best practices. Table of Contents Follow the React tutorial series in order: Lesson 1: React Tutorial \u2014 Introduction (2026) Lesson 2: React Setup \u2014 Create Your First App with Vite Lesson 3: React JSX and Components \u2014 Build Your First UI Lesson 4: React [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":70,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"pagelayer_contact_templates":[],"_pagelayer_content":"","footnotes":""},"categories":[2],"tags":[],"class_list":["post-73","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-react-tutorials"],"_links":{"self":[{"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/posts\/73","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/comments?post=73"}],"version-history":[{"count":3,"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/posts\/73\/revisions"}],"predecessor-version":[{"id":91,"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/posts\/73\/revisions\/91"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/media\/70"}],"wp:attachment":[{"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/media?parent=73"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/categories?post=73"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/react\/wp-json\/wp\/v2\/tags?post=73"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}