React.js 2-way bindings: two-levels deep path in valueLink React.js 2-way bindings: two-levels deep path in valueLink reactjs reactjs

React.js 2-way bindings: two-levels deep path in valueLink


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.jshttps://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.jsBy 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.


I do it without using value-link addon.

Here is a demo: http://wingspan.github.io/wingspan-forms/examples/form-twins/

The secret sauce is to only define one onChange function:

onChange: function (path, /* more paths,*/ value) {    // clone the prior state    // traverse the tree by the paths and assign the value    this.setState(nextState);}

use it like this:

<input     value={this.state['forms']['0']['firstName']}     onChange={_.partial(this.onChange, 'forms', '0', 'firstName')} />

If you have many (value, onChange) pairs that you have to pass around everywhere, it might make sense to define an abstraction around this similar to ReactLink, but I personally got pretty far without using ReactLink.

My colleagues and I recently open sourced wingspan-forms, a React library that helps with with deeply nested state. We leverage this approach heavily. You can see more example demos with linked state on the github page.