background
During the development, after the connect wraps the forwardRef component, the ref reference becomes invalid and returns undefined.
const CompA = React.forwardRef<OutputInterface, IProps>((props, ref) => {
// ...
})
export default connect(mapStateToProps, mapDispatchToProps)(CompA);
reason
Source code: React.forwardRef
From the source code intercepted below, you can see that forwardRef returns an element object, including the type of the element REACT_FORWARD_REF_TYPE
, and the render method of the rendering component function, while connect requires components, so there is a problem with transparent transmission.
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,
) {
// 省略边界条件判断
const elementType = {
$$typeof: REACT_FORWARD_REF_TYPE,
render,
};
if (__DEV__) {
let ownName;
Object.defineProperty(elementType, 'displayName', {
enumerable: false,
configurable: true,
get: function() {
return ownName;
},
set: function(name) {
ownName = name;
if (!render.name && !render.displayName) {
render.displayName = name;
}
},
});
}
return elementType;
}
Solution
Method 1: Call the render method in the return value of forwardRef
const CompA = React.forwardRef<OutputInterface, IProps>((props, ref) => {
// ...
})
// 直接通过render获取渲染组件
export default connect(mapStateToProps, mapDispatchToProps)(CompA.render);
Method 2: The fourth parameter of connect can be set {forwardRef: true} to achieve transparent transmission
const CompA = React.forwardRef<OutputInterface, IProps>((props, ref) => {
// ...
})
// 直接通过render获取渲染组件
export default connect(mapStateToProps, mapDispatchToProps, null, {
forwardRef: true
})(CompA);