英文:
Why doesn't const { innerRef, ...props } = this.props; grab a refrence to this.props.innerRef in react ref forwarding?
问题
在React中,使用ref forwarding(引用转发)时,你可以使用innerRef
来捕获传递给组件的ref。在你提供的代码示例中,你尝试了两种不同的方法。
在第一种方法中,你创建了一个带有innerRef
属性的组件FancybtnWthRef
,然后在Fancybtn
组件内部尝试将innerRef
属性绑定到按钮的ref
上。这种方式不起作用,因为你没有正确地将innerRef
传递给Fancybtn
组件。这个问题可以通过以下方式修复:
class Fancybtn extends React.Component {
constructor(props) {
super(props);
const { innerRef, ...props2 } = this.props;
console.log(innerRef, this.props.innerRef);
}
render() {
return (
<button className="fancy-btn" ref={this.props.innerRef} {...this.props2}>
{this.props.txt}
</button>
);
}
}
在第二种方法中,你直接使用this.props.innerRef
来引用按钮的ref
,这种方式有效,因为你直接使用了this.props.innerRef
,而不是通过解构赋值。
总之,解构赋值不会像你期望的那样在这种情况下工作,因为它不会创建一个实时绑定到this.props
的对象。相反,你需要直接使用this.props.innerRef
来访问innerRef
属性。
英文:
After reading forwarding refs from react legacy docs and following the examples from the SO post on using ref forwarding on classes, I tried to create a working example as following:
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
class Card extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
//after three seconds focus myRef
setTimeout(() => {
console.log(this.myRef);
this.myRef.current.focus();
}, 3000);
}
render() {
return <FancybtnWthRef ref={this.myRef} txt="random"/>;
}
}
//Fancybtn class based componenet with ref forwarding
class Fancybtn extends React.Component {
constructor(props) {
super(props);
const { innerRef, ...props2 } = this.props;
console.log(innerRef, this.props.innerRef); //doesn't get live binding to this.props.innerRef
}
render() {
return (
<button className="fancy-btn" ref={this.innerRef} {...this.props2}>
{this.props.txt}
</button>
);
}
}
const FancybtnWthRef = React.forwardRef((props, ref) => {
return <Fancybtn {...props} innerRef={ref} />;
});
ReactDOM.render(
<Card />,
document.getElementById('root')
);
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
<!-- end snippet -->
On the other hand, if I grab the this.props.innerRef
object directly for button, then it works:
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
class Card extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
//after three seconds focus myRef
setTimeout(() => {
console.log(this.myRef);
this.myRef.current.focus();
}, 3000);
}
render() {
return <FancybtnWthRef ref={this.myRef} txt="random"/>;
}
}
//Fancybtn class based componenet with ref forwarding
class Fancybtn extends React.Component {
constructor(props) {
super(props);
const { innerRef, ...props2 } = this.props;
console.log(innerRef, this.props.innerRef);
}
render() {
return (
<button className="fancy-btn" ref={this.props.innerRef} {...this.props2}>
{this.props.txt}
</button>
);
}
}
const FancybtnWthRef = React.forwardRef((props, ref) => {
return <Fancybtn {...props} innerRef={ref} />;
});
ReactDOM.render(
<Card />,
document.getElementById('root')
);
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
<!-- end snippet -->
In plain javascript destructuring gets live binding of objects as following:
var obj = {x:1, obj2: {y: 33}}
const {x, obj2} = obj;
obj2.y = 44;
cconsole.log(obj.obj2.y); //gives 44
Using the same argument why doesn't const { innerRef, ...props } = this.props;
grab the actual this.props.innerRef
for the button
?
答案1
得分: 2
The code segment const { innerRef, ...props2 } = this.props;
correctly extracts the innerRef
property from props
. However, it creates two local variables and does not set the actual innerRef
property on the instance itself. Therefore, this.innerRef
remains undefined
, and passing it as a ref to the <button>
has no effect. Unlike some other languages like Java, accessing a variable without using this
does not look up that variable in the fields of the enclosing class instance.
To make it work, you need to manually assign the innerRef
to the instance like this:
this.innerRef = innerRef;
Alternatively, if you want to destructure the properties onto this
, you can rename the property as follows:
({ innerRef: this.innerRef, ...this.props2 } = this.props);
英文:
const { innerRef, ...props2 } = this.props;
does correctly get the innerRef
property from props
. However, this creates two local variables. It does not set the actual innerRef
property on the instance itself. Thus, this.innerRef
is undefined
and passing that as the ref to the <button>
has no effect. Note that unlike other languages like Java, accessing a variable without using this
will not attempt to look up that variable in the fields of the enclosing class instance.
You would have to manually assign the innerRef
to the instance to see it work:
this.innerRef = innerRef;
Or, to destructure the properties onto this
, you can rename the property like so:
({ innerRef: this.innerRef, ...this.props2 } = this.props);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论