Verwendung von forwardRef mit FunctionComponent in React Native mithilfe von TypeScript

Oct 22 2020

Ich habe mir viele Dokumente und Beispiele angesehen, aber ich kann immer noch nicht ganz verstehen, wie man forwardRefeine funktionale Komponente mit TypeScript in React Native verwendet. Unten sehen Sie ein Beispiel, in dem ich eine MyCustomComponentmit einer benutzerdefinierten Funktion erstellte, die ich vom übergeordneten Element aufrufen möchte, indem ich eine Referenz erstelle. Da die Referenz jedoch falsch definiert ist und nulloffensichtlich eine Fehlermeldung angezeigt wird, dass die Funktion nicht vorhanden ist. Bitte helfen Sie mir zu verstehen, wie man forwardRefReact Native richtig verwendet . Danke im Voraus!

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>
    )
}

Antworten

3 LindaPaiste Oct 22 2020 at 23:27

Weiterleitung der Ref

Refs können sehr verwirrend sein, da es mehrere Möglichkeiten gibt, mit ihnen umzugehen, und weil die Benutzer den Unterschied zwischen dem ref-Objekt ( React.MutableRefObjectoder React.RefObject) und dem ref-Wert, der in der .currentEigenschaft des ref-Objekts gespeichert ist, nicht kennen . Sie haben diesen Fehler hier zusammen mit einigen fehlenden oder falschen Typoskripttypen gemacht.

useRef<T>ist ein generischer Hook, bei dem der Wert Tangibt, welcher Werttyp gespeichert wird. Wir müssen sagen, Appdass wir beabsichtigen, etwas mit einer coolAlertMethode zu speichern . Eigentlich werden wir später sehen, dass unser Schiedsrichter unveränderlich sein muss, also werden wir ihn createRef<T>stattdessen verwenden.

interface MyRef {
  coolAlert(): void;
}

const MyCustomComponentRef = createRef<MyRef>();

Wenn wir aufrufen onPress, müssen wir auf den aktuellen Wert des ref-Objekts zugreifen. Durch Hinzufügen des Generikums zu createRefkennt Typoskript bereits, dass dieser Wert entweder MyRefoder ist undefined. Wir können coolAlertmit dem optionalen Verkettungsoperator anrufen ?..

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

Jetzt müssen wir noch etwas arbeiten MyCustomComponent. Sie haben sich geirrt, indem Sie ihm den Typ zugewiesen haben, React.FunctionComponent<MyCustomComponentProps>weil eine Funktionskomponente nicht über das erforderliche Wissen über die Weiterleitung von Refs verfügt.

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

Der Typ für MyCustomComponentsollte der komplizierte Rückgabetyp von sein forwardRef. Wir müssen diesen Typ jedoch nicht selbst zuweisen, sondern nur die Generika Tund Pden forwardRefFunktionsaufruf übergeben. Tist der Typ des Schiedsrichters und Pist der Typ der Requisiten.

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

Ok, also haben wir alle Typoskriptfehler beseitigt ! Yay! Außer ... warte. Es macht eigentlich nichts . All das und es funktioniert immer noch nicht. Ich hasse Schiedsrichter. Refs sind schlecht.

Verwenden der Ref

Wir haben den Ref an weitergeleitet MyCustomComponent, der nun Zugriff auf den weitergeleiteten Ref hat und ihn an eine DOM-Komponente anhängen kann. Wir möchten jedoch nicht, dass es an das DOM-Element angehängt wird, sondern an MyCustomComponent. Aber das können wir nicht wirklich tun.

Standardmäßig dürfen Sie das ref-Attribut nicht für Funktionskomponenten verwenden, da diese keine Instanzen [docs] haben.

Wir müssen einen Hook namens verwenden, useImperativeHandleder sich wie eine Hack-Lösung anfühlt, und sogar die Dokumente sagen "Tu das nicht". Ja, ich hasse Schiedsrichter.

useImperativeHandle passt den Instanzwert an, der bei Verwendung von ref für übergeordnete Komponenten verfügbar gemacht wird. Wie immer sollte imperativer Code mit Refs in den meisten Fällen vermieden werden. useImperativeHandle sollte mit forwardRef verwendet werden. [docs]

Wir müssen unsere coolAlertMethode durchsetzen useImperativeHandle.

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

Und jetzt funktioniert es endlich!