# forwardRef
React.forwardRef字面意思理解为转发Ref,它会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。其主要作用是:
# 1.转发refs到DOM组件
ref 不像 props 作为参数可以传递,所以要想传递 ref 得用 forwardRef。
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = useRef(null);
const Father=()=>{
const handleClick=()=>{
const RefValue = ref.current
RefValue.handleCancel() // 可以直接使用被转发的方法
}
return (
<button onClick={handleClick}>
<FancyButton ref={ref}>Click me!</FancyButton>;
)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
因此,当 React 附加了 ref 属性之后,ref.current 将直接指向 DOM 元素实例。
如果一个组件被多次使用,正常情况下想要调用其组件内的方法需要传入props来调用,每次传入的话就比较多余。所以就引入了React.forwardRef。(在tsx中的运用)。
interface SelectFileModalRef {
handleShowModal: () => void;
handleCancel: () => void;
}
const SelectFileModal = forwardRef<SelectFileModalRef, Props>(
(props: Props, ref: Ref<SelectFileModalRef>) => {
useImperativeHandle(ref, () => ({
handleShowModal,
handleCancel,
}));
}
);
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
子组件暴露出来的handleShowModal
和handleCancel
在父组件就可以使用selectFileModalRef.current?.handleShowModal()
来调用进行使用。
# 2.在高阶组件中转发 refs
首先要搞清楚什么是高阶组件:高阶组件(HOC)它是一种基于 React 的组合特性而形成的设计模式。
具体而言,高阶组件是参数为组件,返回值为新组件的函数
// 此函数接收一个组件...
function withSubscription(WrappedComponent, selectData) {
// ...并返回另一个组件...
return class extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
data: selectData(DataSource, props)
};
}
componentDidMount() {
// ...负责订阅相关的操作...
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
data: selectData(DataSource, this.props)
});
}
render() {
// ... 并使用新数据渲染被包装的组件!
// 请注意,我们可能还会传递其他属性
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
如果你对 HOC 添加 ref,该 ref 将引用最外层的容器组件,而不是被包裹的组件。
此时需要用到forwardRef
function logProps(Component) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
const {forwardedRef, ...rest} = this.props;
// 将自定义的 prop 属性 “forwardedRef” 定义为 ref
return <Component ref={forwardedRef} {...rest} />;
}
}
// 注意 React.forwardRef 回调的第二个参数 “ref”。
// 我们可以将其作为常规 prop 属性传递给 LogProps,例如 “forwardedRef”
// 然后它就可以被挂载到被 LogProps 包裹的子组件上。
return React.forwardRef((props, ref) => {
return <LogProps {...props} forwardedRef={ref} />;
});
}
const ref=useref(null)
logProps(<Component data style forwardedRef={ref} />)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25