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.
<textarea>components use the
<input>checkbox and radio components use the
<select>) components use the
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.