# 通过 ref 获取实例
# 类组件中
# 字符串形式
import React, { Component } from 'react';
export default class Demo extends Component {
componentDidMount = () => {
console.log(this.refs); // {currentDom: span}
};
render() {
return <span ref="currentDom">span</span>;
}
}
# 函数形式
import React, { Component } from 'react';
export default class Demo extends Component {
componentDidMount = () => {
console.log(this.currentDom); // span标签
};
render() {
return <span ref={(node) => (this.currentDom = node)}>span</span>;
}
}
# 对象形式
import React, { Component, createRef } from 'react';
export default class Demo extends Component {
constructor(props) {
super(props);
this.currentDom = createRef(null);
}
componentDidMount = () => {
console.log(this.currentDom); // {current: span}
};
render() {
return <span ref={this.currentDom}>span</span>;
}
}
# 函数组件中
在函数组件中我们可以通过 useRef 来获取 DOM 元素或组件的实例。
import React, { useEffect, useRef } from 'react';
export default function() {
const currentDom = useRef(null);
useEffect(() => {
console.log(currentDom); // {current: span}
});
return <span ref={currentDom} />;
}
# ref高阶用法
# forwardRef转发ref
React.forwardRef (opens new window) 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。
# 跨层级获取
import React, { Component } from 'react';
function Son(props) {
return <span ref={props.grandRef}>son</span>;
}
class Father extends Component {
render() {
console.log(this.props, this.props.ref); // props 是一个空对象 {}
return <Son grandRef={this.props.ref} />;
}
}
export default class GrandFather extends Component {
constructor(props) {
super(props);
}
componentDidMount = () => {
console.log(this.node);
};
render() {
return <Father ref={(node) => (this.node = node)} />;
}
}
上面的代码我们想通过向下传递 ref 来获取 Son 组件中的内容,会报错:

我们可以使用 forwardRef 来实现这个需求:
import React, { Component, forwardRef } from 'react';
function Son(props) {
return <span ref={props.grandRef}>son</span>;
}
class Father extends Component {
render() {
console.log(this.props); // this.props -> {grandRef: ƒ}
return <Son grandRef={this.props.grandRef} />;
}
}
const NewFather = forwardRef((props, ref) => <Father grandRef={ref} {...props} />);
export default class GrandFather extends Component {
constructor(props) {
super(props);
}
componentDidMount = () => {
console.log(this.node); // span 标签
};
render() {
return <NewFather ref={(node) => (this.node = node)} />;
}
}
# 合并转发ref
import React, { Component, createRef, forwardRef } from 'react';
class Form extends Component {
constructor(props) {
super(props);
}
render() {
return 'Form'
}
}
class Home extends Component {
constructor(props) {
super(props);
this.form = null;
this.button = null;
}
componentDidMount = () => {
// 可以改写父组件传递过来的 ref
this.props.forwardRef.current = {
form: this.form,
button: this.button
};
};
render() {
return <>
<button ref={button => this.button = button}>按钮</button>
<Form ref={form => this.form = form}/>
</>
}
}
const ForwardRefHome = forwardRef((props, ref) => <Home forwardRef={ref} {...props}/>)
export default class Demo extends Component {
constructor(props) {
super(props);
this.ref = createRef(null);
}
componentDidMount = () => {
console.log(this.ref) // 输出修改后的ref
};
render() {
return <ForwardRefHome ref={this.ref}/>;
}
}
# 高阶组件转发
import React, { Component, forwardRef, useEffect, useRef } from 'react';
const HOC = (Component) => {
class Wrap extends Component {
constructor(props) {
super(props);
}
render() {
const { forwardRef, ...props } = this.props;
return <Component ref={forwardRef} {...props} />;
}
}
// 如果不这样写,ref 指向的就是高阶组件
return forwardRef((props, ref) => <Wrap forwardRef={ref} {...props} />);
};
class Home extends Component {
constructor(props) {
super(props);
}
render() {
return <span>home</span>;
}
}
const HocHome = HOC(Home);
export default () => {
const ref = useRef(null);
useEffect(() => {
console.log(ref);
});
return <HocHome ref={ref} />;
};
注意:
Function components cannot be given refs.