17

我的状态是:

[
  {type: "translateX", x: 10},
  {type: "scaleX", x: 1.2}
]

我正在使用双向绑定助手,但无法为以下内容提供有效的密钥字符串linkState

this.state.map(function(item, i) {
  return <div><input valueLink={this.linkState( ??? )}></div>
}

如果this.linkState接受一些查询语法会很好,例如从我的示例"0.type"中检索 。"translateX"

有什么解决方法吗?


我编写了DeepLinkState mixin,它是 React.addons.LinkedStateMixin 的替代品。使用示例:

this.state.map(function(item, i) {
  return <div><input valueLink={this.linkState([i, "x"])}></div>
}

linkState("0.x")也是可接受的语法。

4

6 回答 6

19

编辑:

我意识到 deep-path forLinkedState非常酷,所以我尝试实现它。
代码:https
://gist.github.com/tungd/8367229 用法:http: //jsfiddle.net/uHm6k/3/


正如文档所述,LinkedState它是一个包装器onChange/setState,适用于简单案例。你总是可以写完整onChange/setState的来实现你想要的。如果你真的想坚持LinkedState,你可以使用非 mixin 版本,例如:

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)
    ...
}

这是工作的 JSFiddle:http: //jsfiddle.net/srbGL/

于 2014-01-11T03:42:28.410 回答
1

如果基本 mixin 不满足您的要求,您可以实现自己的 mixin。

看看这个 mixin 是如何实现的:

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/link.js/

所以你可以很容易地尝试根据上述编写自己的linkState函数。

linkState: function(key,key2) {
  return new ReactLink(
    this.state[key][key2],
    function(newValue) {
      this.state[key][key2] = newValue;
    }
  );
}

请注意,我没有使用ReactStateSetters.createStateKeySetter(this, key). https://github.com/facebook/react/blob/fc73bf0a0abf739a9a8e6b1a5197dab113e76f27/src/core/ReactStateSetters.js 通过再次查看源代码,您会发现此方法没有太多作用,只是它创建了一个函数并且作用很小缓存优化:

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);
  };
}

因此,您绝对应该尝试编写自己的 mixin。如果您的状态中有一个复杂对象并且您想通过对象 API 修改它,这将非常有用。

于 2014-01-25T15:07:22.873 回答
1

我不使用价值链接插件就做到了。

这是一个演示:http ://wingspan.github.io/wingspan-forms/examples/form-twins/

秘诀是只定义一个 onChange 函数:

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

像这样使用它:

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

如果你有很多(value, onChange)对,你必须到处传递,围绕它定义一个类似于 ReactLink 的抽象可能是有意义的,但我个人在没有使用 ReactLink 的情况下已经走了很远。

我和我的同事最近开源了wingspan-forms,这是一个有助于处理深度嵌套状态的React 库。我们大量利用这种方法。您可以在 github 页面上看到更多带有链接状态的示例演示。

于 2014-04-16T21:22:53.523 回答
1

我写了一篇关于它的博文:http: //blog.sendsonar.com/2015/08/04/angular-like-deep-path-data-bindings-in-react/

但基本上我创建了一个新组件,它可以接受父级的“状态”和深度路径,因此您不必编写额外的代码。

<MagicInput binding={[this, 'account.owner.email']} />

还有一个 JSFiddle 所以你可以玩它

于 2015-08-05T20:10:21.873 回答
1

这是解释如何处理此类事情的教程。

React 中的状态和表单,第 3 部分:处理复杂状态

TL;博士:

0) 不要使用标准链接。使用这些.

1)将您的状态更改为如下所示:

collection : [
  {type: "translateX", x: 10},
  {type: "scaleX", x: 1.2}
]

2)链接到collection

var collectionLink = Link.state( this, 'collection' );

3) 遍历其元素的链接:

collectionLink.map(function( itemLink, i ) {
  return <div><input valueLink={itemLink}></div>
})
于 2016-06-02T17:24:04.227 回答
-1

我采用了一种不同的方法,它不使用 mixins 并且不会自动改变状态

github.com/mcmlxxxviii/react-value-link

于 2015-09-15T11:12:04.433 回答