TypeScriptを使用してReactNativeでFunctionComponentでforwardRefを使用する方法
私は多くのドキュメントと例を見てきましたがforwardRef、ReactNativeのTypeScriptで機能コンポーネントを使用する方法をまだ完全に理解していないようです。以下は、MyCustomComponentrefを作成して親から呼び出そうとするカスタム関数を使用してを作成する例です。ただし、refが正しく定義されてnullいないため、関数が存在しないことを示すエラーメッセージが表示されます。forwardRefReactNativeで適切に使用する方法を理解するのを手伝ってください。前もって感謝します!
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>
)
}
回答
参照の転送
refを処理する方法は複数あり、refオブジェクト(React.MutableRefObjectまたはReact.RefObject)と.currentrefオブジェクトのプロパティに格納されているref値の違いに人々が気付いていないため、refは非常に混乱する可能性があります。あなたはここでその間違いを犯し、いくつかのタイプスクリプトタイプが欠落しているか間違っています。
useRef<T>は、T値が格納される値のタイプを示す一般的なフックです。メソッドを使用してApp何かを格納するつもりであることを伝える必要がありますcoolAlert。実際には、後でrefを不変にする必要があることがわかるので、createRef<T>代わりに使用します。
interface MyRef {
coolAlert(): void;
}
const MyCustomComponentRef = createRef<MyRef>();
を呼び出すときはonPress、refオブジェクトの現在の値にアクセスする必要があります。ジェネリックを追加することによりcreateRef、typescriptですが、すでにこの値はどちらかであることを知っています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>(...
[OK]を、私たちは、すべてのtypescriptですエラーを処分しました!わーい!を除いて...ちょっと待ってください。実際には何もしません。そのすべてとそれはまだ動作しません。私はrefsが嫌いです。参照は悪いです。
参照を使用する
参照をに転送しました。これで、転送された参照にMyCustomComponentアクセスでき、DOMコンポーネントにアタッチできます。ただし、DOM要素にアタッチするのではなく、にアタッチする必要がありMyCustomComponentます。しかし、それは実際にはできません。
デフォルトでは、関数コンポーネントにはインスタンスがないため、ref属性を使用できません[ドキュメント]
私たちはuseImperativeHandleハックソリューションのように感じると呼ばれるフックを利用する必要があり、ドキュメントでさえ「これをしないでください」と言っています。うん、私はrefsが嫌いです。
useImperativeHandleは、refを使用するときに親コンポーネントに公開されるインスタンス値をカスタマイズします。いつものように、ほとんどの場合、refを使用する命令型コードは避ける必要があります。useImperativeHandleはforwardRefとともに使用する必要があります。[ドキュメント]
をcoolAlert介してメソッドを公開する必要がありますuseImperativeHandle。
useImperativeHandle(ref , () => ({coolAlert}));
そして今、それは実際に機能します、ついに!