React高阶组件中使用ref
react中forwardRef是用来解决HOC组件使用ref的问题的,所谓HOC就是Higher Order Component,比如使用redux的时候,我们用connect来给组件绑定需要的state,这其中其实就是给我们的组件在外部包了一层组件,然后通过…props的方式把外部的props传入到实际组件。forwardRef的使用方法如下:
const TargetComponent = React.forwardRef((props, ref) => (
<TargetComponent ref={ref} />
))
传递进去,转发displayName;
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} />;
});
}
// 你可以直接获取 DOM 的 ref:
const ref = React.createRef();
const App = logProps(SubApp);
<App ref={ref} />
createRef 源码分析:
import type {RefObject} from 'shared/ReactTypes';
// an immutable object with a single mutable value
export function createRef(): RefObject {
const refObject = {
current: null,
};
return refObject;
}
forwardRef 实现:
import {REACT_FORWARD_REF_TYPE, REACT_MEMO_TYPE} from 'shared/ReactSymbols';
export function forwardRef<Props, ElementType: React$ElementType>(
render: (props: Props, ref: React$Ref<ElementType>) => React$Node,
) {
// render函数必须有两个参数
const elementType = {
$$typeof: REACT_FORWARD_REF_TYPE,
render,
};
return elementType;
}
常见问题:
1、为什么要用ref呢?
ref会指向组件的实例,绑定在dom上可以直接操作dom,例如聚焦input框;绑定在自定义组件上可以在顶部调用自定义组件的方法等。
参考文档:
https://zh-hans.reactjs.org/docs/forwarding-refs.html