"Backwards" ScrollView 的 React Native Typescript 类型

React Native Typescript Typing for "Backwards" ScrollView

我有一个 ScrollView,它首先作为 JavaScript 工作,然后也作为 TypeScript 工作;此 ScrollView 使用 ref 属性 捕获 ScrollView 的引用,然后调用其函数之一 scrollToEnd()。但我最近加强了我的 linting,我需要找出正确的方法来获取此引用 属性 实例类型。

我从这个开始:

import React from "react";
import {ScrollView, StyleProp, ViewStyle} from "react-native";

const standardStyle = {flex:1, backgroundColor:'black'};

export default class ViewClass {
    static produceBackwardScrollingView(customStyle : StyleProp<ViewStyle>, contents : any, horizontal : boolean) {
        let scrollView : any;
        return (
            <ScrollView
                nestedScrollEnabled={true}
                ref={ref => {
                scrollView = ref
            }}
                onContentSizeChange={() => scrollView.scrollToEnd({animated: true})}
                style={[standardStyle, customStyle]}
                horizontal={horizontal}>{contents}</ScrollView>
        );
    }
}

经过与类型的大量角力后,我想出了我认为方向正确的这个,但我仍然遇到 TypeScript 错误。

import React from "react";
import {ScrollView, StyleProp, ViewStyle} from "react-native";

const standardStyle = {flex:1, backgroundColor:'black'};

export default class ViewClass {
    static produceBackwardScrollingView(customStyle : StyleProp<ViewStyle>, contents : any, horizontal : boolean) {
        let scrollView : React.RefObject<ScrollView> | ScrollView | null = React.createRef();
        return (
            <ScrollView
                nestedScrollEnabled={true}
                ref={ref => {
                    // below: scrollView maybe assigned "ScrollView" or "null"
                    scrollView = ref
                }}
                // below: scrollView is possibly null
                // also below: "Property 'scrollToEnd' does not exist on type 'ScrollView | RefObject<ScrollView>'."
                onContentSizeChange={() => scrollView.scrollToEnd({animated: true})}
                style={[standardStyle, customStyle]}
                horizontal={horizontal}>{contents}</ScrollView>
        );
    }
}

我的场景当然使用了 ScrollView,所以我想如果有更好的方法让 ScrollView 从底部开始,应该可以在这种情况下修复我的代码。但我认为这个问题是普遍存在的,因为我真正的主要问题是我无法弄清楚我的对象引用需要什么类型以及如何在其上调用函数。

注意:我对 React Native 和 TypeScript 还是个新手,所以我可能会比较慢。

您的代码将 ref 对象的值与 ref 对象本身混淆了。 ref 是一个带有 属性 current 的对象,其中包含您保存的值。您的类型 let scrollView: React.RefObject<ScrollView> | ScrollView 表示它可以是组件本身 该组件的引用。这就是您收到所有这些错误的原因。

有多种方法可以实现 refs,但让我们坚持你正在做的事情,即使用 React.createRef 创建 ref。这将创建一个引用对象,我们用它来存储组件引用。为了清楚起见,我将重命名它 scrollRef

const scrollRef = React.createRef<ScrollView>(); // has type React.RefObject<ScrollView>

当你在你的回调中使用 ref 时,你需要使用 scrollRef.current 来获取 ScrollView 对象。 React.RefObject<ScrollView>['current'] 的值可以是 ScrollView,也可以是 null,因此在调用 scrollToEnd.

之前我们需要一个可选的链接 ?.
onContentSizeChange={() => scrollRef.current?.scrollToEnd({animated: true})}

对于 ScrollViewref 属性,我们可以传递整个 ref 对象。

ref={scrollRef}

将所有这些放在一起,我们得到:

export default class ViewClass {
    static produceBackwardScrollingView(customStyle : StyleProp<ViewStyle>, contents : any, horizontal : boolean) {
        const scrollRef = React.createRef<ScrollView>();
        return (
            <ScrollView
                nestedScrollEnabled={true}
                ref={scrollRef}
                onContentSizeChange={() => scrollRef.current?.scrollToEnd({animated: true})}
                style={[standardStyle, customStyle]}
                horizontal={horizontal}>{contents}</ScrollView>
        );
    }
}

Typescript Playground Link