{"id":2212,"date":"2021-02-23T05:40:36","date_gmt":"2021-02-23T00:10:36","guid":{"rendered":"http:\/\/uitutorials.in\/wp\/?p=2212"},"modified":"2021-02-23T05:40:36","modified_gmt":"2021-02-23T00:10:36","slug":"uncontrolled-inputs-and-controlled-inputs-forms","status":"publish","type":"post","link":"https:\/\/uitutorials.in\/wp\/uncontrolled-inputs-and-controlled-inputs-forms\/","title":{"rendered":"Uncontrolled Inputs And Controlled Inputs &#8211; Forms"},"content":{"rendered":"<h2>1. Uncontrolled Inputs<\/h2>\n<p>The most basic way of working with forms in React is to use what are referred to as \u201cuncontrolled\u201d form inputs. What this means is that React doesn\u2019t track the input\u2019s state. HTML input elements naturally keep track of their own state as part of the DOM, and so when the form is submitted we have to read the values from the DOM elements themselves.<\/p>\n<p>In order to do this, React allows us to create a \u201cref\u201d (reference) to associate with an element, giving access to the underlying DOM node. Let\u2019s see how to do this:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">class SimpleForm extends React.Component {\r\n  constructor(props) {\r\n    super(props);\r\n    \/\/ create a ref to store the DOM element\r\n    this.nameEl = React.createRef();\r\n    this.handleSubmit = this.handleSubmit.bind(this);\r\n  }\r\n\r\n  handleSubmit(e) {\r\n    e.preventDefault();\r\n    alert(this.nameEl.current.value);\r\n  }\r\n\r\n  render() {\r\n    return (\r\n      &lt;form onSubmit={this.handleSubmit}&gt;\r\n        &lt;label&gt;Name:\r\n          &lt;input type=\"text\" ref={this.nameEl} \/&gt;\r\n        &lt;\/label&gt;\r\n        &lt;input type=\"submit\" name=\"Submit\" \/&gt;\r\n      &lt;\/form&gt;\r\n    )\r\n  }\r\n}\r\n<\/code><\/pre>\n<p>As you can see above, for a class-based component you initialize a new ref in the constructor by calling <strong>React.createRef<\/strong>, assigning it to an instance property so it\u2019s available for the lifetime of the component.<\/p>\n<p>In order to associate the <strong>ref <\/strong>with an input, it\u2019s passed to the element as the special ref attribute. Once this is done, the input\u2019s underlying DOM node can be accessed via <strong>this.nameEl.current<\/strong>.<\/p>\n<p>Let\u2019s see how this looks in a functional component:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">function SimpleForm(props) {\r\n  const nameEl = React.useRef(null);\r\n\r\n  const handleSubmit = e =&gt; {\r\n    e.preventDefault();\r\n    alert(nameEl.current.value);\r\n  };\r\n\r\n  return (\r\n     &lt;form onSubmit={handleSubmit}&gt;\r\n       &lt;label&gt;Name:\r\n         &lt;input type=\"text\" ref={nameEl} \/&gt;\r\n       &lt;\/label&gt;\r\n       &lt;input type=\"submit\" name=\"Submit\" \/&gt;\r\n     &lt;\/form&gt;\r\n   );\r\n}\r\n<\/code><\/pre>\n<p>There\u2019s not a lot of difference here, other than swapping out <strong>createRef <\/strong>for the <strong>useRef <\/strong>hook.<\/p>\n<p><strong>Example: login form<\/strong><\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">function LoginForm(props) {\r\n  const nameEl = React.useRef(null);\r\n  const passwordEl = React.useRef(null);\r\n  const rememberMeEl = React.useRef(null);\r\n\r\n  const handleSubmit = e =&gt; {\r\n    e.preventDefault();\r\n\r\n    const data = {\r\n      username: nameEl.current.value,\r\n      password: passwordEl.current.value,\r\n      rememberMe: rememberMeEl.current.checked,\r\n    }\r\n\r\n    \/\/ Submit form details to login endpoint etc.\r\n    \/\/ ...\r\n  };\r\n\r\n  return (\r\n     &lt;form onSubmit={handleSubmit}&gt;\r\n       &lt;input type=\"text\" placeholder=\"username\" ref={nameEl} \/&gt;\r\n       &lt;input type=\"password\" placeholder=\"password\" ref={passwordEl} \/&gt;\r\n       &lt;label&gt;\r\n         &lt;input type=\"checkbox\" ref={rememberMeEl} \/&gt;\r\n         Remember me\r\n       &lt;\/label&gt;\r\n       &lt;button type=\"submit\" className=\"myButton\"&gt;Login&lt;\/button&gt;\r\n     &lt;\/form&gt;\r\n   );\r\n}\r\n<\/code><\/pre>\n<p><a href=\"https:\/\/codepen.io\/SitePoint\/pen\/rNLjKRB?editors=1111\" rel=\"noopener\" target=\"_blank\">View on CodePen<\/a><\/p>\n<p>While uncontrolled inputs work fine for quick and simple forms, they do have some drawbacks. As you might have noticed from the code above, we have to read the value from the input element whenever we want it. This means we can\u2019t provide instant validation on the field as the user types, nor can we do things like enforce a custom input format, conditionally show or hide form elements, or disable\/enable the submit button.<\/p>\n<p>Fortunately, there\u2019s a more sophisticated way to handle inputs in React.<\/p>\n<h2>2. Controlled Inputs<\/h2>\n<p>An input is said to be \u201ccontrolled\u201d when React is responsible for maintaining and setting its state. The state is kept in sync with the input\u2019s value, meaning that changing the input will update the state, and updating the state will change the input.<\/p>\n<p>Let\u2019s see what that looks like with an example:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">class ControlledInput extends React.Component {\r\n  constructor(props) {\r\n    super(props);\r\n    this.state = { name: '' };\r\n    this.handleInput = this.handleInput.bind(this);\r\n  }\r\n\r\n  handleInput(event) {\r\n    this.setState({\r\n      name: event.target.value\r\n    });\r\n  }\r\n\r\n  render() {\r\n    return (\r\n      &lt;input type=\"text\" value={this.state.name} onChange={this.handleInput} \/&gt;\r\n    );\r\n  }\r\n}\r\n<\/code><\/pre>\n<p>As you can see, we set up a kind of circular data flow: state to input value, on change event to state, and back again. This loop allows us a lot of control over the input, as we can react to changes to the value on the fly. Because of this, controlled inputs don\u2019t suffer from the limitations of uncontrolled ones, opening up the follow possibilities:<\/p>\n<p><strong>instant input validation:<\/strong> we can give the user instant feedback without having to wait for them to submit the form (e.g. if their password is not complex enough)<br \/>\n<strong>instant input formatting:<\/strong> we can add proper separators to currency inputs, or grouping to phone numbers on the fly<br \/>\n<strong>conditionally disable form submission:<\/strong> we can enable the submit button after certain criteria are met (e.g. the user consented to the terms and conditions)<br \/>\n<strong>dynamically generate new inputs:<\/strong> we can add additional inputs to a form based on the user\u2019s previous input (e.g. adding details of additional people on a hotel booking)<\/p>\n<h2>Validation<\/h2>\n<p>As I mentioned above, the continuous update loop of controlled components makes it possible to perform continuous validation on inputs as the user types. A handler attached to an input\u2019s onChange event will be fired on every keystroke, allowing you to instantly validate or format the value.<\/p>\n<h3>Example: credit card validation<\/h3>\n<p>Let\u2019s take a look at a real-word example of checking a credit card number as the user types it into a payment form.<\/p>\n<p>The example uses a library called <a href=\"https:\/\/github.com\/braintree\/credit-card-type\" rel=\"noopener\" target=\"_blank\">credit-card-type<\/a> to determine the card issuer (such as Amex, Visa, or Mastercard) as the user types. The component then uses this information to display an image of the issuer logo next to the input:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">import  creditCardType  from  \"credit-card-type\";\r\n\r\nfunction CreditCardForm(props) {\r\n  const [cardNumber, setCardNumber] = React.useState(\"\");\r\n  const [cardTypeImage, setCardTypeImage] = React.useState(\r\n    \"card-logo-unknown.svg\"\r\n  );\r\n\r\n  const handleCardNumber = (e) =&gt; {\r\n    e.preventDefault();\r\n\r\n    const value = e.target.value;\r\n    setCardNumber(value);\r\n\r\n    let suggestion;\r\n\r\n    if (value.length &gt; 0) {\r\n      suggestion = creditCardType(e.target.value)[0];\r\n    }\r\n\r\n    const cardType = suggestion ? suggestion.type : \"unknown\";\r\n\r\n    let imageUrl;\r\n\r\n    switch (cardType) {\r\n      case \"visa\":\r\n        imageUrl = \"card-logo-visa.svg\";\r\n        break;\r\n      case \"mastercard\":\r\n        imageUrl = \"card-logo-mastercard.svg\";\r\n        break;\r\n      case \"american-express\":\r\n        imageUrl = \"card-logo-amex.svg\";\r\n        break;\r\n      default:\r\n        imageUrl = \"card-logo-unknown.svg\";\r\n    }\r\n\r\n    setCardTypeImage(imageUrl);\r\n  };\r\n\r\n  return (\r\n    &lt;form&gt;\r\n      &lt;div className=\"card-number\"&gt;\r\n        &lt;input\r\n          type=\"text\"\r\n          placeholder=\"card number\"\r\n          value={cardNumber}\r\n          onChange={handleCardNumber}\r\n        \/&gt;\r\n        &lt;img src={cardTypeImage} alt=\"card logo\" \/&gt;\r\n      &lt;\/div&gt;\r\n      &lt;button type=\"submit\" className=\"myButton\"&gt;\r\n        Login\r\n      &lt;\/button&gt;\r\n    &lt;\/form&gt;\r\n  );\r\n}\r\n<\/code><\/pre>\n<p>The input\u2019s <strong>onChange <\/strong>handler calls the <strong>creditCardType()<\/strong> function with the current value. This returns an array of matches (or an empty array) which can be used to determine which image to display. The image URL is then set to a state variable to be rendered into the form.<\/p>\n<h3>Reference<\/h3>\n<p><a href=\"https:\/\/www.sitepoint.com\/work-with-forms-in-react\/\" rel=\"noopener\" target=\"_blank\">work-with-forms-in-react<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Uncontrolled Inputs The most basic way of working with forms in React is to use what are referred to as \u201cuncontrolled\u201d form inputs. What this means is that React doesn\u2019t track the input\u2019s state. HTML input elements naturally keep track of their own state as part of the DOM,<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[106],"tags":[107,129],"class_list":["post-2212","post","type-post","status-publish","format-standard","hentry","category-react","tag-react","tag-react-form","ct-col-2"],"_links":{"self":[{"href":"https:\/\/uitutorials.in\/wp\/wp-json\/wp\/v2\/posts\/2212","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/uitutorials.in\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/uitutorials.in\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/uitutorials.in\/wp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/uitutorials.in\/wp\/wp-json\/wp\/v2\/comments?post=2212"}],"version-history":[{"count":2,"href":"https:\/\/uitutorials.in\/wp\/wp-json\/wp\/v2\/posts\/2212\/revisions"}],"predecessor-version":[{"id":2214,"href":"https:\/\/uitutorials.in\/wp\/wp-json\/wp\/v2\/posts\/2212\/revisions\/2214"}],"wp:attachment":[{"href":"https:\/\/uitutorials.in\/wp\/wp-json\/wp\/v2\/media?parent=2212"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/uitutorials.in\/wp\/wp-json\/wp\/v2\/categories?post=2212"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/uitutorials.in\/wp\/wp-json\/wp\/v2\/tags?post=2212"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}