如何使用TypeScript在React Native中将ForwardRef与FunctionComponent一起使用

时间:2020-10-22 18:51:12

标签: javascript reactjs typescript react-native

我看过许多文档和示例,但我似乎仍然不太了解如何在React Native的TypeScript中将forwardRef与功能组件一起使用。下面是一个使用自定义函数创建MyCustomComponent的示例,我尝试通过创建引用从父函数调用该函数。但是,由于ref的定义不正确且null,显然我收到一条错误消息,告诉我该函数不存在。请帮助我了解如何在React Native中正确使用forwardRef。预先感谢!

interface MyCustomComponentProps {
    title: string
}

const MyCustomComponent: React.FunctionComponent<MyCustomComponentProps> = React.forwardRef((props, ref) => {
    const coolAlert = () => {
        Alert.alert('Hey!', 'This was called from MyCustomComponent')
    }
    return (
        <View>
            <Text>{props.title}</Text>
        </View>
    )
})

export default function App () {
    const MyCustomComponentRef = useRef()
    return (
        <SafeAreaView>
            <MyCustomComponent ref={MyCustomComponentRef} title='Hello World' />
            <TouchableOpacity
                onPress={() => {
                    MyCustomComponentRef.coolAlert()
                }}>
                <Text>Click Me</Text>
            </TouchableOpacity>
        </SafeAreaView>
    )
}

1 个答案:

答案 0 :(得分:3)

转发参考

引用确实会造成混乱,因为有多种处理方法,而且人们并不了解ref对象(React.MutableRefObjectReact.RefObject)与ref值之间的区别,即存储在ref对象的.current属性上。您在这里犯了这个错误,以及一些缺少或不正确的打字稿类型。

useRef<T>是一个通用钩子,其中值T表示将存储哪种类型的值。我们需要告诉App,我们打算使用coolAlert方法存储某些内容。实际上,稍后我们会看到我们需要将引用保持不变,因此我们将改用createRef<T>

interface MyRef {
  coolAlert(): void;
}

const MyCustomComponentRef = createRef<MyRef>();

调用onPress时,需要访问ref对象的当前值。通过将泛型添加到createRef中,打字稿已经知道该值为MyRefundefined。我们可以使用可选的链接coolAlert运算符来调用?.

onPress={() => MyCustomComponentRef.current?.coolAlert()}

现在,我们需要对MyCustomComponent做一些工作。您将其分配为类型React.FunctionComponent<MyCustomComponentProps>的原因是错误的,因为功能组件不具备我们所需的引用转发知识。

function forwardRef<T, P = {}>(Component: RefForwardingComponent<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;

MyCustomComponent的类型应该是forwardRef的返回类型。但是我们不需要自己分配该类型,我们只需要将泛型TP传递给forwardRef函数调用即可。 T是裁判的类型,P是道具的类型。

const MyCustomComponent = React.forwardRef<MyRef, MyCustomComponentProps>(...

好吧,我们got rid of all the typescript errors!好极了!除了...高举。实际上,它没有做任何事情。所有这些,仍然不起作用。 我讨厌裁判。推荐人不好。

使用参考

我们已将引用转发给MyCustomComponent,后者现在可以访问转发的引用并将其附加到DOM组件。但是我们不希望它附加到DOM元素,我们希望它附加到MyCustomComponent。但是我们真的不能做到这一点。

默认情况下,您不能在功能组件上使用ref属性,因为它们没有实例[docs]

我们必须使用一个名为useImperativeHandle的钩子,它看起来像是一种黑客解决方案,甚至文档都说“不要这样做”。是的,我讨厌裁判。

useImperativeHandle自定义使用ref时公开给父组件的实例值。 一如既往,在大多数情况下,应避免使用引用的命令性代码。 useImperativeHandle应该与forwardRef一起使用。 [docs]

我们必须通过coolAlert公开我们的useImperativeHandle方法。

useImperativeHandle(ref , () => ({coolAlert}));

现在it actually works,终于!