forwardRef,咋一看长的和useRef很像,既然很像,那么功能必定相似,因此猜想也是使用ref来引用一个DOM的。猜想对不对先不管,可以先回顾一下useRef,这样的话可以方便做个对比。
react官网对forwardRef的解释很简单,大致如下:
React.forwardRef
会创建一个React组件,这个组件能够将其接受的ref
属性转发到其组件树下的另一个组件中。
React.forwardRef
接受渲染函数作为参数。React 将使用 props 和 ref 作为参数来调用此函数。此函数应返回 React 节点。
先对其简单归纳出一个初始印象:
-
React.forwardRef
返回的是一个组件 -
React.forwardRef
接受一个函数作为参数,这个函数是一个渲染函数,也就是一个组件 - 该渲染函数接受 props 和 ref 作为参数
这里有一个很简单的例子先看看到底是怎么使用的:
import ReactDOM from "react-dom";
import React, { Component, createRef, forwardRef } from "react";
const FocusInput = forwardRef((props, ref) => (
<div>
<input type="text" ref={ref} />
</div>
));
class App extends Component {
constructor(props) {
super(props);
this.ref = createRef();
}
onButtonClick = () => {
this.ref.current.focus();
};
render() {
return (
<div>
<button onClick={this.onButtonClick}>Focus the input</button>
子组件内容:{this.ref.current.value}
<FocusInput ref={this.ref} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
从这个例子的使用中来看,forwardRef与useRef完全不是同一个东西,前者的形态是类似于一个高阶函数(不直接接受组件作为参数,但仍返回一个组件),只是在参数函数中向其传入 ref 参数,然后内部 ref 附着给谁,谁就被外界使用this.ref.current
拿到。
看起来forwardRef实现的功能就是外层组件可以通过 ref 直接控制内层组件或元素的行为,简单的来说,就像其名字给出的信号:透传。
上面这个例子如果不使用forwardRef会报出错误。ref不能直接用在一个函数式组件上,需要使用forwardRef将该函数组件包裹,否则爆出如下错误:
那么如果用在一个calss组件上,并且将其传入class组件内部元素上呢?答案式无法做到。经过尝试,calss组件上只能在组件层面使用ref,而其内部元素是无法使用的。
constructor(props, ref) {
super();
this.inputRef = ref; // 1.尝试给到一个变量
}
render() {
return (<div>
<input type="text" />
<input type="text" ref ={this.inputRef} /> // 2.很明显是错误的语法
</div>)
}
}
因此forWardRef就解决了这个透传的问题。