【发布时间】:2017-06-12 02:46:28
【问题描述】:
我一直在测试使用React.cloneElement() 扩展组件的children 可能存在的限制/危险。我发现的一种可能的危险是可能会覆盖 ref 和 key 等道具。
但是,根据 React 的 0.13 release candidate(早在 2015 年):
但是,与 JSX 和 cloneWithProps 不同的是,它还保留了 refs。这意味着如果你得到一个带有 ref 的孩子,你不会不小心从你的祖先那里偷走它。您将获得附加到新元素的相同 ref。
[...]
注意:
React.cloneElement(child, { ref: 'newRef' })确实会覆盖 ref,因此两个父母仍然不可能拥有同一个孩子的 ref,除非您使用 callback-refs。
我写了一个small React application,它克隆了被推送的子组件,在两个级别上测试了引用的有效性:
class ChildComponent extends React.Component{
constructor(props){
super(props);
this.onClick = this.onClick.bind(this);
this.extendsChildren = this.extendChildren(this);
}
onClick(e) {
e.preventDefault();
try{
alert(this._input.value);
}catch(e){
alert('ref broken :(');
}
}
extendChildren(){
return React.Children.map(this.props.children, child => {
return React.cloneElement(
child,
{
ref: ref => this._input = ref
}
);
});
}
render() {
return(
<div>
<button onClick={this.onClick}>
ChildComponent ref check
</button>
{this.extendChildren()}
</div>
);
}
}
class AncestorComponent extends React.Component{
constructor(props){
super(props);
this.onClick = this.onClick.bind(this);
}
onClick(e) {
e.preventDefault();
try{
alert(this._input.value);
}catch(e){
alert('ref broken :(');
}
}
render() {
return (
<div>
<p>
The expected behaviour is that I should be able to click on both Application and ChildComponent check buttons and have a reference to the input (poping an alert with the input's value).
</p>
<button onClick={this.onClick}>
Ancestor ref check
</button>
<ChildComponent>
<input ref={ref => this._input = ref} defaultValue="Hello World"/>
</ChildComponent>
</div>
);
}
}
但是,我的 ChildComponent 中的 cloningElements 会覆盖来自输入字段的 AncestorComponent 的 ref 属性,我希望在其中保留 ref 属性,以及我定义为 React.cloneElement 的一部分的新 ref。
您可以通过运行 CodePen 进行测试。
是我做错了什么,还是从那以后这个功能被删除了?
【问题讨论】:
标签: javascript reactjs