javascript - 如何使用 TypeScript 在 React Native 中使用 forwardRef 和 FunctionComponent
问题描述
我查看了许多文档和示例,但我似乎仍然不太了解如何forwardRef
在 React Native 中使用带有 TypeScript 的功能组件。下面是一个示例,其中我创建了MyCustomComponent
一个自定义函数,我尝试通过创建一个 ref 从父级调用该函数。但是,由于 ref 的定义不正确null
,我显然会收到一条错误消息,告诉我该函数不存在。请帮助我了解如何forwardRef
在 React Native 中正确使用。提前致谢!
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>
)
}
解决方案
转发参考
Refs 可能真的很令人困惑,因为有多种方法可以处理它们,而且人们不知道 ref 对象(React.MutableRefObject
或React.RefObject
)和 ref 值之间的区别,ref 值存储在.current
ref 对象的属性中。您在这里犯了这个错误,以及一些缺失或不正确的打字稿类型。
useRef<T>
是一个通用钩子,其中值T
告诉将存储什么类型的值。我们需要告诉App
我们打算用coolAlert
方法存储一些东西。实际上我们稍后会看到我们需要我们的 ref 是不可变的,所以我们将使用它createRef<T>
。
interface MyRef {
coolAlert(): void;
}
const MyCustomComponentRef = createRef<MyRef>();
当我们调用 时onPress
,我们需要访问 ref 对象的当前值。通过将泛型添加到createRef
,打字稿已经知道这个值是MyRef
or undefined
。我们可以coolAlert
使用可选的链接?.
运算符进行调用。
onPress={() => MyCustomComponentRef.current?.coolAlert()}
现在我们需要对MyCustomComponent
. 您错误地为其分配了类型React.FunctionComponent<MyCustomComponentProps>
,因为函数组件不具备我们需要的关于 ref 转发的知识。
function forwardRef<T, P = {}>(Component: RefForwardingComponent<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;
for 的类型MyCustomComponent
应该是 from 的复杂返回类型forwardRef
。但是我们不需要自己分配那个类型,我们只需要传递泛型和T
函数调用。 是 ref的类型,是 props 的类型。P
forwardRef
T
P
const MyCustomComponent = React.forwardRef<MyRef, MyCustomComponentProps>(...
好的,所以我们摆脱了所有打字稿错误!耶!除了……等一下。它实际上并没有做任何事情。所有这些,它仍然不起作用。 我讨厌裁判。裁判很糟糕。
使用参考
我们将 ref 转发给MyCustomComponent
,他现在可以访问转发的 ref 并可以将其附加到 DOM 组件。但是我们不希望它附加到 DOM 元素,我们希望它附加到MyCustomComponent
. 但我们真的做不到。
默认情况下,您可能不会在函数组件上使用 ref 属性,因为它们没有实例[docs]
我们必须使用一个叫做 hack 的钩子useImperativeHandle
,它感觉像是一个 hack 解决方案,甚至文档都说“不要这样做”。是的,我讨厌裁判。
useImperativeHandle 自定义使用 ref 时暴露给父组件的实例值。与往常一样,在大多数情况下应避免使用 refs 的命令式代码。useImperativeHandle 应该与 forwardRef 一起使用。[文档]
我们必须coolAlert
通过useImperativeHandle
.
useImperativeHandle(ref , () => ({coolAlert}));
现在它终于可以正常工作了!
推荐阅读
- xml - 如何获取父标签中的所有元素并使用 XSLT 进行排序?
- ruby-on-rails - 在 Rails 中禁用 SSL 重定向的方法
- python-3.x - 基本 If 语句单元测试
- python - 如何让我的变量成为 tkinter 中输入框的输入?
- xcode - Xcode 12.0 调试视图不显示变量
- python - Django 3.1.1 未找到静态文件
- javascript - 调整大小和移动多边形后如何获取多边形点的新位置
- prolog - 为什么这个序言的输出是yes/true?
- pine-script - 在交易视图版本 4 的价格图表上绘制/叠加基本数据“EPS”
- python - Azure 函数使用 ssh 访问私有 github 存储库