React Native自定义类组件中measureInWindow无法使用的问题
我有一个类组件CustomerMainView,其中包含自定义按钮ImageButton(简化代码如下)。尝试通过ref调用ImageButton的measureInWindow方法获取其相对于窗口的位置时,一直报错:"Property 'measureInWindow' does not exist on type 'ImageButton'"。但将ImageButton替换为View或TouchableHighlight等React Native原生组件则可正常运行。请问问题出在哪里,如何让自定义组件支持该方法?
代码示例
CustomerMainView组件
class CustomerMainView extends Component<CustomerMainViewProps> { private qr_btn_loc: LayoutRectangle; private btn_ref: RefObject<ImageButton>; constructor(props: CustomerMainViewProps) { super(props); this.qr_btn_loc = { x: 0, y: 0, width: 0, height: 0 }; this.btn_ref = createRef<ImageButton>(); } render(): ReactNode { return ( <View style={this.props.style}> <ImageButton ref={this.btn_ref} style={style.button} image={require("./qr.png")} onLayout={(l: LayoutChangeEvent) => { this.btn_ref.current?.measureInWindow((x: number, y: number, width: number, height: number) => { this.qr_btn_loc = {x, y, width, height}; }) }} onPress={() => { console.log(this.qr_btn_loc); }} ></ImageButton> </View> ); } }
ImageButton组件
interface ImageButtonProps extends TouchableHighlightProps { image: ImageSourcePropType; } class ImageButton extends Component<ImageButtonProps> { constructor(props: any) { super(props); } render(): ReactNode { return ( <TouchableHighlight {...this.props}> <Image style={style.img} source={this.props.image}></Image> </TouchableHighlight> ); } }
问题原因
measureInWindow是React Native原生视图组件(如View、TouchableHighlight)的实例方法,你的自定义ImageButton组件本身并没有这个方法——它只是封装了原生组件,但默认不会将内部原生组件的方法暴露给外部ref,因此TypeScript会抛出类型错误。
解决方法
需要在ImageButton中创建指向内部原生组件的ref,并通过组件实例暴露measureInWindow方法,同时完善TypeScript类型定义:
修改后的ImageButton组件
import { TouchableHighlight, Image, ImageSourcePropType, TouchableHighlightProps, createRef, RefObject } from 'react-native'; import { Component, ReactNode } from 'react'; interface ImageButtonProps extends TouchableHighlightProps { image: ImageSourcePropType; } // 定义组件实例需暴露的方法类型 interface ImageButtonInstance { measureInWindow: (callback: (x: number, y: number, width: number, height: number) => void) => void; } class ImageButton extends Component<ImageButtonProps> implements ImageButtonInstance { // 创建指向内部TouchableHighlight的ref private touchableRef: RefObject<TouchableHighlight> = createRef<TouchableHighlight>(); constructor(props: ImageButtonProps) { super(props); } // 暴露measureInWindow方法,转发给内部原生组件 measureInWindow(callback: (x: number, y: number, width: number, height: number) => void) { this.touchableRef.current?.measureInWindow(callback); } render(): ReactNode { // 将ref绑定到内部TouchableHighlight return ( <TouchableHighlight {...this.props} ref={this.touchableRef}> <Image style={style.img} source={this.props.image} /> </TouchableHighlight> ); } } // 示例样式 const style = { img: { width: 40, height: 40 } };
验证修改
修改后,CustomerMainView中的原有代码无需调整,TypeScript会自动识别ImageButton实例上的measureInWindow方法,报错消失,且能正常获取组件位置。
补充说明
如果需要暴露更多原生组件的方法,都可以通过这种方式在自定义组件中封装转发。若使用函数组件,也可以通过forwardRef实现ref转发,但上述方案更适配你当前的类组件结构。
内容的提问来源于stack exchange,提问作者FutureCake

