These docs are old and won’t be updated. Go toreact.dev for the new React docs.
These new documentation pages teach modern React and include live examples:
HTML form elements work a bit differently from other DOM elements in React, because form elements naturally keep some internal state. For example, this form in plain HTML accepts a single name:
<form><label> Name:<inputtype="text"name="name"/></label><inputtype="submit"value="Submit"/></form>This form has the default HTML form behavior of browsing to a new page when the user submits the form. If you want this behavior in React, it just works. But in most cases, it’s convenient to have a JavaScript function that handles the submission of the form and has access to the data that the user entered into the form. The standard way to achieve this is with a technique called “controlled components”.
In HTML, form elements such as<input>,<textarea>, and<select> typically maintain their own state and update it based on user input. In React, mutable state is typically kept in the state property of components, and only updated withsetState().
We can combine the two by making the React state be the “single source of truth”. Then the React component that renders a form also controls what happens in that form on subsequent user input. An input form element whose value is controlled by React in this way is called a “controlled component”.
For example, if we want to make the previous example log the name when it is submitted, we can write the form as a controlled component:
classNameFormextendsReact.Component{constructor(props){super(props);this.state={value:''};this.handleChange=this.handleChange.bind(this);this.handleSubmit=this.handleSubmit.bind(this);}handleChange(event){this.setState({value: event.target.value});}handleSubmit(event){alert('A name was submitted: '+this.state.value); event.preventDefault();}render(){return(<formonSubmit={this.handleSubmit}><label> Name:<inputtype="text"value={this.state.value}onChange={this.handleChange}/></label><inputtype="submit"value="Submit"/></form>);}}Since thevalue attribute is set on our form element, the displayed value will always bethis.state.value, making the React state the source of truth. SincehandleChange runs on every keystroke to update the React state, the displayed value will update as the user types.
With a controlled component, the input’s value is always driven by the React state. While this means you have to type a bit more code, you can now pass the value to other UI elements too, or reset it from other event handlers.
In HTML, a<textarea> element defines its text by its children:
<textarea> Hello there, this is some text in a text area</textarea>In React, a<textarea> uses avalue attribute instead. This way, a form using a<textarea> can be written very similarly to a form that uses a single-line input:
classEssayFormextendsReact.Component{constructor(props){super(props);this.state={value:'Please write an essay about your favorite DOM element.'};this.handleChange=this.handleChange.bind(this);this.handleSubmit=this.handleSubmit.bind(this);}handleChange(event){this.setState({value: event.target.value});}handleSubmit(event){alert('An essay was submitted: '+this.state.value); event.preventDefault();}render(){return(<formonSubmit={this.handleSubmit}><label> Essay:<textareavalue={this.state.value}onChange={this.handleChange}/></label><inputtype="submit"value="Submit"/></form>);}}Notice thatthis.state.value is initialized in the constructor, so that the text area starts off with some text in it.
In HTML,<select> creates a drop-down list. For example, this HTML creates a drop-down list of flavors:
<select><optionvalue="grapefruit">Grapefruit</option><optionvalue="lime">Lime</option><optionselectedvalue="coconut">Coconut</option><optionvalue="mango">Mango</option></select>Note that the Coconut option is initially selected, because of theselected attribute. React, instead of using thisselected attribute, uses avalue attribute on the rootselect tag. This is more convenient in a controlled component because you only need to update it in one place. For example:
classFlavorFormextendsReact.Component{constructor(props){super(props);this.state={value:'coconut'};this.handleChange=this.handleChange.bind(this);this.handleSubmit=this.handleSubmit.bind(this);}handleChange(event){this.setState({value: event.target.value});}handleSubmit(event){alert('Your favorite flavor is: '+this.state.value); event.preventDefault();}render(){return(<formonSubmit={this.handleSubmit}><label> Pick your favorite flavor:<selectvalue={this.state.value}onChange={this.handleChange}><optionvalue="grapefruit">Grapefruit</option><optionvalue="lime">Lime</option><optionvalue="coconut">Coconut</option><optionvalue="mango">Mango</option></select></label><inputtype="submit"value="Submit"/></form>);}}Overall, this makes it so that<input type="text">,<textarea>, and<select> all work very similarly - they all accept avalue attribute that you can use to implement a controlled component.
Note
You can pass an array into the
valueattribute, allowing you to select multiple options in aselecttag:<selectmultiple={true}value={['B','C']}>
In HTML, an<input type="file"> lets the user choose one or more files from their device storage to be uploaded to a server or manipulated by JavaScript via theFile API.
<inputtype="file"/>Because its value is read-only, it is anuncontrolled component in React. It is discussed together with other uncontrolled componentslater in the documentation.
When you need to handle multiple controlledinput elements, you can add aname attribute to each element and let the handler function choose what to do based on the value ofevent.target.name.
For example:
classReservationextendsReact.Component{constructor(props){super(props);this.state={isGoing:true,numberOfGuests:2};this.handleInputChange=this.handleInputChange.bind(this);}handleInputChange(event){const target= event.target;const value= target.type==='checkbox'? target.checked: target.value;const name= target.name;this.setState({[name]: value});}render(){return(<form><label> Is going:<inputname="isGoing"type="checkbox"checked={this.state.isGoing}onChange={this.handleInputChange}/></label><br/><label> Number of guests:<inputname="numberOfGuests"type="number"value={this.state.numberOfGuests}onChange={this.handleInputChange}/></label></form>);}}Note how we used the ES6computed property name syntax to update the state key corresponding to the given input name:
this.setState({[name]: value});It is equivalent to this ES5 code:
var partialState={};partialState[name]= value;this.setState(partialState);Also, sincesetState() automaticallymerges a partial state into the current state, we only needed to call it with the changed parts.
Specifying thevalue prop on acontrolled component prevents the user from changing the input unless you desire so. If you’ve specified avalue but the input is still editable, you may have accidentally setvalue toundefined ornull.
The following code demonstrates this. (The input is locked at first but becomes editable after a short delay.)
ReactDOM.createRoot(mountNode).render(<inputvalue="hi"/>);setTimeout(function(){ ReactDOM.createRoot(mountNode).render(<inputvalue={null}/>);},1000);It can sometimes be tedious to use controlled components, because you need to write an event handler for every way your data can change and pipe all of the input state through a React component. This can become particularly annoying when you are converting a preexisting codebase to React, or integrating a React application with a non-React library. In these situations, you might want to check outuncontrolled components, an alternative technique for implementing input forms.
If you’re looking for a complete solution including validation, keeping track of the visited fields, and handling form submission,Formik is one of the popular choices. However, it is built on the same principles of controlled components and managing state — so don’t neglect to learn them.