javascript React.js 2 路绑定:valueLink 中的两级深度路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21057219/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React.js 2-way bindings: two-levels deep path in valueLink
提问by NVI
My state is:
我的状态是:
[
{type: "translateX", x: 10},
{type: "scaleX", x: 1.2}
]
I'm using Two-Way Binding Helpersand I can't provide a valid key string for linkState
:
我正在使用双向绑定助手,但无法为以下各项提供有效的密钥字符串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.
如果this.linkState
接受一些查询语法会很好,例如从我的示例中"0.type"
检索 "translateX"
。
Are there any workarounds?
有什么解决方法吗?
I wrote DeepLinkState mixinwhich is a drop-in replacement for React.addons.LinkedStateMixin. Usage example:
我写了DeepLinkState mixin,它是 React.addons.LinkedStateMixin 的直接替代品。用法示例:
this.state.map(function(item, i) {
return <div><input valueLink={this.linkState([i, "x"])}></div>
}
linkState("0.x")
is also acceptable syntax.
linkState("0.x")
也是可接受的语法。
回答by tungd
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/
我意识到 deep-path forLinkedState
非常酷,所以我尝试实现它。
代码:https
: //gist.github.com/tungd/8367229用法: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:
正如文档所述,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)
...
}
Here is working JSFiddle: http://jsfiddle.net/srbGL/
这是工作 JSFiddle:http: //jsfiddle.net/srbGL/
回答by gaperton
Here's the tutorial explaining how to handle things like this.
这是解释如何处理此类事情的教程。
State and Forms in React, Part 3: Handling the Complex State
TL;DR:
特尔;博士:
0) Don't use standard links. Use these.
0) 不要使用标准链接。使用这些。
1) Change your state to look like this:
1) 将您的状态更改为如下所示:
collection : [
{type: "translateX", x: 10},
{type: "scaleX", x: 1.2}
]
2) Take link to the collection
:
2)获取链接到collection
:
var collectionLink = Link.state( this, 'collection' );
3) Iterate through the links to its elements:
3) 遍历指向其元素的链接:
collectionLink.map(function( itemLink, i ) {
return <div><input valueLink={itemLink}></div>
})
回答by Sebastien Lorber
You can implement your own mixin if the base mixin doesn't satisfy you.
如果基本 mixin 不满足您,您可以实现自己的 mixin。
See how this mixin is implemented:
看看这个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.jshttps://github.com/facebook/react/blob/fc73bf0a0abf739a9a8e6b1a5197dab113e76f27/src/addons/link/ReactLink.js
https://github.com/facebook/react/blob/fc73bf0a0abf739a9a8e6b1a5197dab113e76f27/src/addons/link/LinkedStateMixin.js https://github.com/facebook/react/blob/fc73bf0a0abf7397a7a2fc73bf0a0abf7397a7a2d/fc73bf0a0abf7397a7a2f7397a7a2f7397a7a2a2f7397a7a2a2f739bf737a9a1a2f27/src/addons/link/LinkedStateMixin.js
So you can easily try to write your own linkState
function based on the above.
因此,您可以轻松地尝试linkState
根据上述内容编写自己的函数。
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:
请注意,我没有使用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);
};
}
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.
因此,您绝对应该尝试编写自己的 mixin。如果您的状态中有一个复杂的对象并且您想通过对象 API 修改它,这将非常有用。
回答by Dustin Getz
I do it without using value-link addon.
我没有使用价值链接插件。
Here is a demo: http://wingspan.github.io/wingspan-forms/examples/form-twins/
这是一个演示:http: //wingspan.github.io/wingspan-forms/examples/form-twins/
The secret sauce is to only define one onChange function:
秘诀是只定义一个 onChange 函数:
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.
如果您有许多(value, onChange)
必须在任何地方传递的对,那么围绕它定义一个类似于 ReactLink 的抽象可能是有意义的,但我个人在没有使用 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.
我和我的同事最近开源了wingspan-forms,这是一个有助于处理深度嵌套状态的React 库。我们大量利用这种方法。您可以在 github 页面上看到更多带有链接状态的示例演示。
回答by M?chael Makar?v
I wrote a blogpost about it: http://blog.sendsonar.com/2015/08/04/angular-like-deep-path-data-bindings-in-react/
我写了一篇关于它的博文:http: //blog.sendsonar.com/2015/08/04/angular-like-deep-path-data-bindings-in-react/
But basically I created a new component that would accept the 'state' of parent and a deep path, so you don't have to write extra code.
但基本上我创建了一个新组件,它可以接受父级的“状态”和深度路径,因此您不必编写额外的代码。
<MagicInput binding={[this, 'account.owner.email']} />
There's a JSFiddle too so you can play with it
还有一个 JSFiddle 所以你可以玩它
回答by mcmlxxxviii
I took a different approach which does not employ mixins and does not automatically mutate the state
我采用了一种不同的方法,它不使用 mixin 并且不会自动改变状态