Pru*_*rus 6 javascript reactjs
我一直在测试使用React.cloneElement()扩展组件的可能的局限性/危险性children。我发现的一种可能的危险是可能会覆盖诸如ref和的道具key。
但是,根据React的0.13版本候选对象(早在2015年):
但是,与JSX和cloneWithProps不同,它还保留引用。这意味着,如果您得到一个带有裁判的孩子,则不会意外地从祖先那里偷走它。您将获得与新元素相同的引用。
[...]
注意:
React.cloneElement(child, { ref: 'newRef' })确实会覆盖该引用,因此除非您使用回调引用,否则两个父母仍然不可能对同一个孩子拥有一个引用。
我编写了一个小的React应用程序,该应用程序克隆了推入的子组件,并在两个级别上测试ref的有效性:
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>
);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,ChildComponent内部的cloningElements会覆盖ref输入字段中的AncestorComponent的prop,我希望在该字段ref中保留该prop,以及ref我定义为的新对象React.cloneElement。
您可以通过运行CodePen进行测试。
我做错什么了吗,或者此功能此后被删除了?
根据Dan Abramov的响应,即使使用回调,覆盖引用仍将覆盖引用。您需要在回调声明中调用当前引用:
return React.Children.map(this.props.children, child =>
React.cloneElement(child, {
ref(node) {
// Keep your own reference
this._input = node;
// Call the original ref, if any
const {ref} = child;
if (typeof ref === 'function') {
ref(node);
}
}
)
);
Run Code Online (Sandbox Code Playgroud)