UPDATE (2016-07-28): As of React v15
checkedLink are officially deprecated. I heavily advocate the use of both of these APIs in this article. If you want to see my thoughts on the deprecation see this comment below. For the official deprecation see the docs article here.
With React, you basically get two different ways to deal with forms:
- Standard input elements that can be modified by the user
- “Controlled” input elements that can only be modified programatically
The first type is pretty straightforward in React, you simply don’t provide a
The value of that
<input> element can be edited by the user in a browser, just like one would expect in a normal we app.
The other type of input—a “Controlled” input—looks almost the same, but has a
The value of this
<input> element will stubbornly refuse to change no matter what the user does. This is generally a terrible user experience, so React will actually warn you that your input cannot be modified:
If you’re new-ish to React you might not know why you would want to do this. The answer is state. React puts a big emphasis on explicitly keeping your components state in the
state property. So in order to create a form input that responds to user input you will need to use two-way data binding. Meaning the
value of the
<input> element will flow from your component into the DOM, but also from the DOM into your component. In other words, they will be kept in sync.
The most common way to accomplish two-way data binding in React is to be explicit. This is by design, and it’s a good practice for smaller forms. Here’s how an example:
Here we’ve bound our input’s change event to the component’s
onChange function which will update
this.state is updated the component will be re-rendered, causing the input value to reflect what the user typed.
If that’s not quite clear, I highly recommend taking a look at the Forms guide on the React website.
The code above is explicit and not overly complicated, which is great for maintainabillty. There are virtually no downsides to this approach when dealing with a small form that only contains a few inputs. Issues only begin to crop up when you have many inputs that all need to update state.
That’s why we have…
React comes with a handy mixin to help you achieve two-way data-binding very quickly. Use the LinkedStateMixin to save yourself soem hassle when wiring up large forms to stay in sync with component state:
As you can see we replaced the
value prop with
valueLink. If you haven’t heard of
valueLink I’ll explain it in a sec.
LinkedStateMixin saves us a good deal of typing, and especially when you have a large number of form fields that need to be tied to component state. The issue is that it’s not very flexible. Essentially it just binds the value of an input field to
this.state. But what if you are building a stateless form component that gets all it’s values from props? Or, more interestingly, what if you are using Flux and don’t want to set state directly but rather call an action that updates a store?
This is what
valueLink is great for.
valueLink prop is a fairly under-documented feature of form inputs in React that simplifies the onChange / setState pattern described at the beginning of this post. It’s a shortcut for telling an input where to get its
value prop from and what function to call when an
onChange event is fired. In it’s most simple form the
valueLink prop points to a plain old JS object with two distinct props:
value: The value of the input at any given time
requestChange: The function to call whenever
onChangeis fired on the input.
requestChangewill be called with the update value of the input, so there’s no need to access the value using an event object as you might do if you were using the actual
If you’re familiar with React’s PropTypes feature then this expression of
valueLink as a
propType should make it clear what you’re going for:
Let’s check out an example.
Now you will get the same two-way data binding as you did when using the
LinkedStateMixin. What we’ve done here is basically created our own version of the
LinkedStateMixin to demonstrate how
You can use
valueLink to bind the
value prop of any input to the state of a component. If you instead want to set state on a parent component you can pass a
valueLink down as a prop just like you would do with an
The other important point to note is that some input types, namely
<input type='radio'> and
<input type='checkbox'> use the
checked prop because they represent boolean values. They still use a
value prop to determine what value corresponds to the
checked prop, but it’s only the
checked prop that can be changed by the user.
React acknowledges this and provides us with the
checkedLink prop, which works exactly like
valueLink except it binds the
checked prop to state instead of the
Note that when using
checkedLink the shape of the object you pass in is still exactly the same, i.e. it needs a
value prop and a
requestChange prop. This is good because it means we can use our
makeValueLink function to bind any type of input to state including checkboxes and radios.
The importance of
valueLink really shines when you’re using something like Flux where you don’t actually want to update
this.state directly but would like instead for data to flow through actions to stores which control the UI state. Using
valueLink makes this is quite easy:
Now whenever you check the checkbox
AppActions.doSomething will be called with a
'booleanValue' and a
newValue of either
false depending on whether or not it is checked.
AppActions you would do whatever you want with the data and most likely dispatch it to all stores so they could update their state accordingly.
AppStore would get the dispatch and update it’s internal representation of state
Hope all this helps as you build forms with React.