Input elements present an interesting problem with React's virtual DOM. With the traditional DOM, you render the input or textarea and let the browser manage the state (its value). You can then get and set the value imperatively with the DOM API. How does this play with React's declarative model?
In this article, we are going to focus on a text input element, although the concept is the same for textareas, radio inputs, and other form elements.
What do you expect the behavior of <input value="Hello!" />
to be? It'd make sense for the input to be rendered initially with the value "Hello" but what happens when the user tries to change the value? Let's find out.
As you can see, setting the value of an input freezes the value. This may be surprising at first but it makes sense that if the value did change, the virtual DOM would be out of sync with the actual DOM. So how do we get a working input?
We can take advantage of the onChange
attribute, which is called every time the input value tries to change. Notice that this behavior is differen than the DOM change event. This was a point of debate for the core React developers and in the end, they decided using "change" made more sense than introducing another event. Now, we can create a component with the state and callbacks we know.
This is called a controlled component, where the input's value is decided by the code. Contrast this to an uncontrolled component, which you create by not providing a value
prop. In this example, we show two input implementations with the same behavior.
With the uncontrolled input, notice the use of defaultValue
and refs to interact with the DOM. While controlled inputs better match the React programming model, there are times when an uncontrolled input would suffice. There is overhead using a controlled input as React needs to perform an update on every change event (every keystroke), so you may prefer an uncontrolled input for performance.
In this article, we use the text inputs but the behavior is similar for other form elements.
<input>
and <textarea>
components use the value
attribute.<input>
checkbox and radio components use the checked
attribute.<option>
(within <select>
) components use the selected
attribute.It is interesting how controlled inputs are implemented by the framework. Check out ReactDOMInput and ChangeEventPlugin for some light reading.
For more information, check out the official docs on forms.
Children are an essential tool to create modular and reusable components. Take a look at how this.props.children
works with JSX and the utilities we can use.
Subscribe for a range of articles from React basics to advanced topics such as performance optimization and deep dives in the React source code.