navigation Navigation


Einführung


React Referenzen (Refs) ermöglichen den direkten Zugriff auf DOM-Elemente oder Komponenteninstanzen, um beispielsweise Fokussteuerung, Animationen oder Integration mit Drittanbieter-Bibliotheken zu realisieren. Portale erweitern dieses Konzept, indem sie es erlauben, React-Komponenten außerhalb der regulären DOM-Hierarchie zu rendern. Dies ist besonders nützlich für modale Fenster, Tooltips oder Overlays, die unabhängig vom normalen Komponentenbaum dargestellt werden sollen. Zusammen bilden Refs und Portale grundlegende Werkzeuge, um erweiterte Interaktionen und komplexe UI-Strukturen in React-Anwendungen umzusetzen.

Inhaltsverzeichnis

    Problem

    Verwendung von Formularen ohne spezifische Unterstützung seitens React Hooks kann etwas umständlich sein. Man steht immer vor der Aufgabe an die Werte aus den Formularen heran zu kommen.

    Damit wir besser verstehen was gemeint ist und ein Beispiel vor Augen haben, definieren wir folgendes Component.

    FormWithoutRef.jsx
    import { useState } from 'react';
    
    const FormWithoutRef = () => {
        const [fieldUsername, setFieldUsername] = useState('');
    
        const handleUpdateUsername = (event) => {
            setFieldUsername(event.target.value);
        };
    
        const handleSubmitForm = (event) => {
            event.preventDefault();
    
            // Hier z.B. Daten an den Server senden
        };
    
        return (
            <form onSubmit={handleSubmitForm}>
                <label htmlFor="fieldUsername">Benutzername</label>
                <input
                    type="text"
                    id="fieldUsername"
                    name="fieldUsername"
                    onChange={handleUpdateUsername}
                />
                <button>Submit</button>
            </form>
        );
    };
    
    export default FormWithoutRef;

    Technisch funktioniert dieses Beispiel, ist aber einiges an Code. In diesem Beispiel benötigen wir die Zustandsverwaltung hauptsächlich für das Auslesen des Benutzernamens, um es an den Server zu senden.

    Obwohl fieldUsername eigentlich von der Funktion handleSubmitForm() benötigt wird, führt React den gesamten Code des Components aus, wenn ein change-Event durch die Eingabe im Input-Feld ausgelöst wird. Also, bei jeder Tasteneingabe.

    An dieser Stelle könnte man all diese Ausführungen durch React und u.U. auch etwas an Performance einsparen, indem man auf Vanilla JavaScript umsteigt und die Felder in etwa wie folgt ausliest.

    const inputUsername = document.getElementById("fieldUsername");
    const usernameValue = inputUsername.value;

    Das Problem an dieser Herangehensweise ist, dass hier kein React verwendet wird. Und wenn man mit React eine Anwendung aufbaut, sollte man unbedingt innerhalb von React bleiben.

    Versuche, JavaScript am React vorbei oder nicht nach React-Art einzusetzen, könnten im fehlerhaften und unerwarteten Verhalten enden. Vor allem, wenn es um die UI-Aktualisierung geht. Macht man hier etwas nicht nach React-Art, kann es ebenfalls Probleme geben.

    Lösung - useRef()

    Um uns dennoch auf native DOM-Elemente zugreifen zu lassen, stellt uns React den Kontext “Refs” (References oder Referenzen) bereit. Referenzen (Ref) ist eine Möglichkeit, Referenzen auf Werte zu speichern, beispielsweise auf DOM-Elemente, aus einem Component heraus.

    Um eine Referenz zu erzeugen, gibt es useRef() Hook. Damit kann man eine Referenz erstellen.

    Irgendwo im Code können wir also Folgendes tun.

    import { useRef } from 'react';
    
    const MyComponent = () => {
        const refFieldUsername = useRef(null);
    };
    
    export default MyComponent;

    Damit haben wir eine Referenz erzeugt, welche leer (null) ist. Wir können nun in unserem JSX-Template diese Referenz an ein DOM-Element binden und dadurch den Zugriff auf dieses Element über diese Referenz (Brücke) zu erhalten.

    Nun stellen wir unser Beispiel auf die Verwendung von useRef() um.

    FormWithRef.jsx
    import { useState } from 'react';
    
    const FormWithRef = () => {
        const refFieldUsername = useRef(null);
    
        const handleSubmitForm = (event) => {
            event.preventDefault();
            console.log(refFieldUsername.current.value);
        };
    
        return (
            <form onSubmit={handleSubmitForm}>
                <label htmlFor="fieldUsername">Benutzername</label>
                <input
                    type="text"
                    id="fieldUsername"
                    name="fieldUsername"
                    ref={refFieldUsername}
                />
                <button>Submit</button>
            </form>
        );
    };
    
    export default FormWithRef;

    Wichtiger Hinweis

    Um das Element aus dem Referenz-Objekt (Rückgabewert der useRef() Funktion) anzusprechen, müssen wir über die current Eigenschaft gehen. Anders formuliert: In current befindet sich die Referenz auf das Objekt.

    Als Ergebnis haben wir das identische Formular und beim Klick auf den Submit-Button oder durch das Auslösen des submit-Events erhalten wir den Wert des referenzierten Eingabefeldes in Konsole ausgegeben.

    React useRef() - Beispiel Zugriff auf Input-Element

    In diesem Beispiel erhält die useRef() Funktion null als initialen Startwert übergeben, da es technisch noch keinem DOM-Element zugewiesen wurde, wenn die Component-Funktion (FormWithRef) zum ersten Mal ausgeführt wird. Eine Referenzierung erfolgt erst nach dem initialen Render-Vorgang.

    Nach der ersten Ausführung wird der Wert von useRef() das referenzierte DOM-Element sein.

    Um den Wert nach der initialen Ausführung erneut zu prüfen, simulieren wir es mithilfe von useState() und einem völlig sinnlosen Wert. Wie wir wissen, wird die Component-Funktion beim Aufruf der State-Update-Funktion erneut ausgeführt.

    Wir aktualisieren unser Beispiel-Code wie folgt und schauen was wir in der Konsole nach dem Klick auf den Button “Update value” erhalten.

    FormWithRef.jsx
    import { useRef, useState } from 'react';
    
    const FormWithRef = () => {
    
        const [sampleValue, setSampleValue] = useState(0);
    
        const refFieldUsername = useRef(null);
        console.log('Direct after assignment', refFieldUsername);
    
        const handleUpdateSampleValue = () => {
            setSampleValue(current => 1);
        };
    
        const handleSubmitForm = (event) => {
            event.preventDefault();
            console.log(refFieldUsername.current.value);
        };
    
        return (
            <form onSubmit={handleSubmitForm}>
                <label htmlFor="fieldUsername">Benutzername</label>
                <input
                    type="text"
                    name="fieldUsername"
                    id="fieldUsername"
                    ref={refFieldUsername}
                />
                <button>Submit</button>
                <button onClick={handleUpdateSampleValue}>Update value</button>
            </form>
        );
    
    };
    
    export default FormWithRef;

    React useRef() - Referenz nach der zweiten Ausführung der Component Funktion