You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
5.4 KiB
132 lines
5.4 KiB
11 years ago
|
---
|
||
11 years ago
|
id: two-way-binding-helpers
|
||
8 years ago
|
title: Two-way Binding Helpers
|
||
9 years ago
|
permalink: docs/two-way-binding-helpers.html
|
||
8 years ago
|
layout: docs
|
||
|
category: Add-Ons
|
||
11 years ago
|
---
|
||
|
|
||
11 years ago
|
> Note:
|
||
8 years ago
|
>
|
||
8 years ago
|
> `LinkedStateMixin` is deprecated as of React v15. The recommendation is to explicitly set the value and change handler, instead of using `LinkedStateMixin`.
|
||
|
|
||
|
**Importing**
|
||
|
|
||
|
```javascript
|
||
8 years ago
|
import LinkedStateMixin from 'react-addons-linked-state-mixin'; // ES6
|
||
|
var LinkedStateMixin = require('react-addons-linked-state-mixin'); // ES5 with npm
|
||
8 years ago
|
```
|
||
|
|
||
|
## Overview
|
||
|
|
||
|
`LinkedStateMixin` is an easy way to express two-way binding with React.
|
||
11 years ago
|
|
||
8 years ago
|
In React, data flows one way: from owner to child. We think that this makes your app's code easier to understand. You can think of it as "one-way data binding."
|
||
11 years ago
|
|
||
|
However, there are lots of applications that require you to read some data and flow it back into your program. For example, when developing forms, you'll often want to update some React `state` when you receive user input. Or perhaps you want to perform layout in JavaScript and react to changes in some DOM element size.
|
||
|
|
||
7 years ago
|
In React, you would implement this by listening to a "change" event, read from your data source (usually the DOM) and call `setState()` on one of your components. "Closing the data flow loop" explicitly leads to more understandable and easier-to-maintain programs. See [our forms documentation](/docs/forms.html) for more information.
|
||
11 years ago
|
|
||
8 years ago
|
Two-way binding -- implicitly enforcing that some value in the DOM is always consistent with some React `state` -- is concise and supports a wide variety of applications. We've provided `LinkedStateMixin`: syntactic sugar for setting up the common data flow loop pattern described above, or "linking" some data source to React `state`.
|
||
11 years ago
|
|
||
|
> Note:
|
||
|
>
|
||
8 years ago
|
> `LinkedStateMixin` is just a thin wrapper and convention around the `onChange`/`setState()` pattern. It doesn't fundamentally change how data flows in your React application.
|
||
11 years ago
|
|
||
8 years ago
|
## LinkedStateMixin: Before and After
|
||
11 years ago
|
|
||
8 years ago
|
Here's a simple form example without using `LinkedStateMixin`:
|
||
11 years ago
|
|
||
|
```javascript
|
||
8 years ago
|
var createReactClass = require('create-react-class');
|
||
|
|
||
|
var NoLink = createReactClass({
|
||
11 years ago
|
getInitialState: function() {
|
||
11 years ago
|
return {message: 'Hello!'};
|
||
11 years ago
|
},
|
||
|
handleChange: function(event) {
|
||
11 years ago
|
this.setState({message: event.target.value});
|
||
11 years ago
|
},
|
||
|
render: function() {
|
||
11 years ago
|
var message = this.state.message;
|
||
|
return <input type="text" value={message} onChange={this.handleChange} />;
|
||
11 years ago
|
}
|
||
|
});
|
||
|
```
|
||
|
|
||
8 years ago
|
This works really well and it's very clear how data is flowing, however, with a lot of form fields it could get a bit verbose. Let's use `LinkedStateMixin` to save us some typing:
|
||
11 years ago
|
|
||
9 years ago
|
```javascript{4,9}
|
||
8 years ago
|
var createReactClass = require('create-react-class');
|
||
|
|
||
|
var WithLink = createReactClass({
|
||
9 years ago
|
mixins: [LinkedStateMixin],
|
||
11 years ago
|
getInitialState: function() {
|
||
11 years ago
|
return {message: 'Hello!'};
|
||
11 years ago
|
},
|
||
|
render: function() {
|
||
11 years ago
|
return <input type="text" valueLink={this.linkState('message')} />;
|
||
11 years ago
|
}
|
||
|
});
|
||
|
```
|
||
|
|
||
8 years ago
|
`LinkedStateMixin` adds a method to your React component called `linkState()`. `linkState()` returns a `valueLink` object which contains the current value of the React state and a callback to change it.
|
||
11 years ago
|
|
||
8 years ago
|
`valueLink` objects can be passed up and down the tree as props, so it's easy (and explicit) to set up two-way binding between a component deep in the hierarchy and state that lives higher in the hierarchy.
|
||
11 years ago
|
|
||
11 years ago
|
Note that checkboxes have a special behavior regarding their `value` attribute, which is the value that will be sent on form submit if the checkbox is checked (defaults to `on`). The `value` attribute is not updated when the checkbox is checked or unchecked. For checkboxes, you should use `checkedLink` instead of `valueLink`:
|
||
11 years ago
|
```
|
||
11 years ago
|
<input type="checkbox" checkedLink={this.linkState('booleanValue')} />
|
||
11 years ago
|
```
|
||
|
|
||
11 years ago
|
## Under the Hood
|
||
|
|
||
8 years ago
|
There are two sides to `LinkedStateMixin`: the place where you create the `valueLink` instance and the place where you use it. To prove how simple `LinkedStateMixin` is, let's rewrite each side separately to be more explicit.
|
||
11 years ago
|
|
||
8 years ago
|
### valueLink Without LinkedStateMixin
|
||
11 years ago
|
|
||
8 years ago
|
```javascript{7-9,11-14}
|
||
|
var createReactClass = require('create-react-class');
|
||
|
|
||
|
var WithoutMixin = createReactClass({
|
||
11 years ago
|
getInitialState: function() {
|
||
11 years ago
|
return {message: 'Hello!'};
|
||
11 years ago
|
},
|
||
|
handleChange: function(newValue) {
|
||
11 years ago
|
this.setState({message: newValue});
|
||
11 years ago
|
},
|
||
|
render: function() {
|
||
|
var valueLink = {
|
||
11 years ago
|
value: this.state.message,
|
||
11 years ago
|
requestChange: this.handleChange
|
||
|
};
|
||
|
return <input type="text" valueLink={valueLink} />;
|
||
|
}
|
||
|
});
|
||
|
```
|
||
|
|
||
8 years ago
|
As you can see, `valueLink` objects are very simple objects that just have a `value` and `requestChange` prop. And `LinkedStateMixin` is similarly simple: it just populates those fields with a value from `this.state` and a callback that calls `this.setState()`.
|
||
11 years ago
|
|
||
8 years ago
|
### LinkedStateMixin Without valueLink
|
||
11 years ago
|
|
||
|
```javascript
|
||
9 years ago
|
var LinkedStateMixin = require('react-addons-linked-state-mixin');
|
||
8 years ago
|
var createReactClass = require('create-react-class');
|
||
9 years ago
|
|
||
8 years ago
|
var WithoutLink = createReactClass({
|
||
9 years ago
|
mixins: [LinkedStateMixin],
|
||
11 years ago
|
getInitialState: function() {
|
||
11 years ago
|
return {message: 'Hello!'};
|
||
11 years ago
|
},
|
||
|
render: function() {
|
||
11 years ago
|
var valueLink = this.linkState('message');
|
||
11 years ago
|
var handleChange = function(e) {
|
||
|
valueLink.requestChange(e.target.value);
|
||
|
};
|
||
|
return <input type="text" value={valueLink.value} onChange={handleChange} />;
|
||
|
}
|
||
|
});
|
||
|
```
|
||
|
|
||
|
The `valueLink` prop is also quite simple. It simply handles the `onChange` event and calls `this.props.valueLink.requestChange()` and also uses `this.props.valueLink.value` instead of `this.props.value`. That's it!
|