我看过许多文档和示例,但我似乎仍然不太了解如何在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>
)
}
答案 0 :(得分:3)
引用确实会造成混乱,因为有多种处理方法,而且人们并不了解ref对象(React.MutableRefObject
或React.RefObject
)与ref值之间的区别,即存储在ref对象的.current
属性上。您在这里犯了这个错误,以及一些缺少或不正确的打字稿类型。
useRef<T>
是一个通用钩子,其中值T
表示将存储哪种类型的值。我们需要告诉App
,我们打算使用coolAlert
方法存储某些内容。实际上,稍后我们会看到我们需要将引用保持不变,因此我们将改用createRef<T>
。
interface MyRef {
coolAlert(): void;
}
const MyCustomComponentRef = createRef<MyRef>();
调用onPress
时,需要访问ref对象的当前值。通过将泛型添加到createRef
中,打字稿已经知道该值为MyRef
或undefined
。我们可以使用可选的链接coolAlert
运算符来调用?.
。
onPress={() => MyCustomComponentRef.current?.coolAlert()}
现在,我们需要对MyCustomComponent
做一些工作。您将其分配为类型React.FunctionComponent<MyCustomComponentProps>
的原因是错误的,因为功能组件不具备我们所需的引用转发知识。
function forwardRef<T, P = {}>(Component: RefForwardingComponent<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;
MyCustomComponent
的类型应该是forwardRef
的返回类型。但是我们不需要自己分配该类型,我们只需要将泛型T
和P
传递给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,终于!