My state is:
[
{type: "translateX", x: 10},
{type: "scaleX", x: 1.2}
]
I’m using Two-Way Binding Helpers and I can’t provide a valid key string for linkState
:
this.state.map(function(item, i) {
return <div><input valueLink={this.linkState( ??? )}></div>
}
Would be nice if this.linkState
accepted some query syntax, such as "0.type"
to retrieve "translateX"
from my example.
Are there any workarounds?
I wrote DeepLinkState mixin which is a drop-in replacement for React.addons.LinkedStateMixin. Usage example:
this.state.map(function(item, i) {
return <div><input valueLink={this.linkState([i, "x"])}></div>
}
linkState("0.x")
is also acceptable syntax.
Edit:
I realized that deep-path for LinkedState
is pretty cool so I try to implement it.
The code: https://gist.github.com/tungd/8367229
Usage: http://jsfiddle.net/uHm6k/3/
As the document stated, LinkedState
is a wrapper around onChange/setState
and meant for simple case. You can always write the full onChange/setState
to achieve what you want. If you really want to stick with LinkedState
, you can use the non mixin version, for example:
getInitialState: function() {
return { values: [
{ type: "translateX", x: 10 },
{ type: "scaleX", x: 1.2 }
]}
},
handleTypeChange: function(i, value) {
this.state.values[i].type = value
this.setState({ values: this.state.values })
},
render: function() {
...
this.state.values.map(function(item, i) {
var typeLink = {
value: this.state.values[i].type,
requestChange: this.handleTypeChange.bind(null, i)
}
return <div><input valueLink={typeLink}/></div>
}, this)
...
}
Here is working JSFiddle: http://jsfiddle.net/srbGL/
You can implement your own mixin if the base mixin doesn't satisfy you.
See how this mixin is implemented:
var LinkedStateMixin = {
/**
* Create a ReactLink that's linked to part of this component's state. The
* ReactLink will have the current value of this.state[key] and will call
* setState() when a change is requested.
*
* @param {string} key state key to update. Note: you may want to use keyOf()
* if you're using Google Closure Compiler advanced mode.
* @return {ReactLink} ReactLink instance linking to the state.
*/
linkState: function(key) {
return new ReactLink(
this.state[key],
ReactStateSetters.createStateKeySetter(this, key)
);
}
};
/**
* @param {*} value current value of the link
* @param {function} requestChange callback to request a change
*/
function ReactLink(value, requestChange) {
this.value = value;
this.requestChange = requestChange;
}
https://github.com/facebook/react/blob/fc73bf0a0abf739a9a8e6b1a5197dab113e76f27/src/addons/link/LinkedStateMixin.js https://github.com/facebook/react/blob/fc73bf0a0abf739a9a8e6b1a5197dab113e76f27/src/addons/link/ReactLink.js
So you can easily try to write your own linkState
function based on the above.
linkState: function(key,key2) {
return new ReactLink(
this.state[key][key2],
function(newValue) {
this.state[key][key2] = newValue;
}
);
}
Notice that I didn't use the ReactStateSetters.createStateKeySetter(this, key)
.
https://github.com/facebook/react/blob/fc73bf0a0abf739a9a8e6b1a5197dab113e76f27/src/core/ReactStateSetters.js
By looking at the source code again you can find out this method doesn't do so much except it creates a function and does little caching optimizations:
function createStateKeySetter(component, key) {
// Partial state is allocated outside of the function closure so it can be
// reused with every call, avoiding memory allocation when this function
// is called.
var partialState = {};
return function stateKeySetter(value) {
partialState[key] = value;
component.setState(partialState);
};
}
So you should definitely try to write your own mixin. This can be very useful if you have in your state a complex object and you want to modify it through the object API.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With