You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Ref转发中,解构this.props为何无法获取innerRef引用?

类组件中Ref转发的解构绑定问题

我在阅读React Legacy文档的Ref转发内容,参考相关类组件Ref转发示例后,写了以下代码:

无法正常工作的代码示例

class Card extends React.Component {

  constructor(props) {
    super(props);
    this.myRef = React.createRef();
    // 3秒后让myRef指向的元素获取焦点
    setTimeout(() => {
      console.log(this.myRef);
      this.myRef.current.focus();
    }, 3000);
  }

  render() {
    return <FancybtnWthRef ref={this.myRef} txt="random"/>;
  }
}

// 带Ref转发的类组件Fancybtn
class Fancybtn extends React.Component {
  constructor(props) {
    super(props);
    const { innerRef, ...props2 } = this.props;
    console.log(innerRef, this.props.innerRef); // 无法获取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')
);

这段代码无法获取this.props.innerRef的实时绑定,但如果直接在button上使用this.props.innerRef,就能正常工作:

正常工作的代码示例

class Card extends React.Component {

  constructor(props) {
    super(props);
    this.myRef = React.createRef();
    // 3秒后让myRef指向的元素获取焦点
    setTimeout(() => {
      console.log(this.myRef);
      this.myRef.current.focus();
    }, 3000);
  }

  render() {
    return <FancybtnWthRef ref={this.myRef} txt="random"/>;
  }
}

// 带Ref转发的类组件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>
    );
  }
}

const FancybtnWthRef = React.forwardRef((props, ref) => {
  return <Fancybtn {...props} innerRef={ref} />;
});

ReactDOM.render(
  <Card />,
  document.getElementById('root')
);

在普通JavaScript里,对象解构是有实时绑定的,比如:

普通JS解构的对比示例

var obj = {x:1, obj2: {y: 33}}
const {x, obj2} = obj;
obj2.y = 44;
console.log(obj.obj2.y); // 输出44

按照同样的逻辑,为什么在React中const { innerRef, ...props } = this.props;无法让button获取到有效的this.props.innerRef引用?


回答

问题核心出在类组件构造函数的执行时机和Ref的赋值逻辑上:

  1. 类组件的constructor仅在初始化时执行一次,此时解构this.props.innerRef拿到的是初始状态的Ref对象,但这个Ref的current属性还未被React赋值为DOM元素——React会在组件挂载完成后,才会把DOM元素赋值给Ref的current。
  2. 你在constructor里解构出innerRef后,并没有把它挂载到组件实例(this)上,所以render里的this.innerRef本质是undefined,自然无法绑定到button上。而直接使用this.props.innerRef时,render阶段引用的是实时的props对象,当React完成挂载赋值Ref的current后,这个引用能直接生效。

另外要明确:普通JS里的解构实时绑定,是因为解构的是对象引用,但这里的问题并非解构本身的绑定失效,而是你没有正确保存解构出的Ref引用,且构造函数执行时Ref的current还未完成赋值。

如果要让第一种写法生效,需要在constructor里把解构出的innerRef挂载到实例上:

class Fancybtn extends React.Component {
  constructor(props) {
    super(props);
    this.innerRef = props.innerRef; // 将props中的innerRef赋值给实例属性
    const { innerRef, ...props2 } = this.props;
    this.props2 = props2; // 保存剩余props到实例
  }

  render() {
    return (
      <button className="fancy-btn" ref={this.innerRef} {...this.props2}>
        {this.props.txt}
      </button>
    );
  }
}

不过更简洁合理的做法,还是直接在render中使用this.props.innerRef,避免多余的实例属性赋值操作。


内容的提问来源于stack exchange,提问作者user31782

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 07:57:26