navigation Navigation


useImperativeHandle()


Der useImperativeHandle Hook ist eine spezialisierte Funktion in React, die es ermöglicht, die über ein Ref-Objekt nach außen freigegebene Instanz eines Komponenten anzupassen. Während React generell einen deklarativen Datenfluss bevorzugt, bietet dieser Hook die Möglichkeit, präzise zu kontrollieren, welche Funktionen und Eigenschaften Elternkomponenten durch eine Ref zugänglich gemacht werden. Dies ist besonders nützlich, wenn komplexe Komponenten bestimmte Methoden nach außen exponieren müssen, ohne ihre interne Implementierung vollständig preiszugeben. Der useImperativeHandle Hook wird typischerweise in Verbindung mit forwardRef verwendet und ermöglicht eine saubere Kapselung bei gleichzeitiger Bereitstellung einer kontrollierten imperativen API.

Inhaltsverzeichnis

    Einführung

    Problem verstehen

    In React gibt es klassischen Datenfluß. Von oben (Eltern-Komponenten) nach unten (Kind-Komponenten). Das wird in der Regel mit Props umgesetzt. In umgekehrte Richtung (von Kind-Komponente zu Eltern-Komponente) werden normalerweise Callbacks verwendet.

    Manchmal benötigt man jedoch eine direkte Möglichkeit als Eltern-Komponente direkt eine Methode in der Kind-Komponente aufzurufen. Genau hier kommt useImperativeHandle ins Spiel!

    Was ist useImperativeHandle

    useImperativeHandle erlaubt es, spezielle Methoden einer Kind-Komponente für die Eltern-Komponente verfügbar zu machen. Damit lässt sich eine Art “Brücke” aufbauen, die diese Verbindung ermöglicht.

    Beispiel 1

    Am besten lässt sich das anhand einem Beispiel besser verstehen. In diesem Beispiel werden zwei Komponenten definieren.

    Kind-Komponente wird ein Eingabe-Feld beinhalten, welches wir über die Eltern-Komponente manipulieren möchten.

    Eltern-Komponente wird Buttons (Actions) bereitstellen, mit denen wir etwas mit dem Eingabefeld in der Kind-Komponente tun möchten.

    Wir fangen mit der Kind-Komponente an.

    ChildComponent.jsx
    import { useRef, useState, useImperativeHandle } from 'react';
    
    function ChildComponent({ props, ref }) {
    
        const [inputValue, setInputValue] = useState('');
        const refInputElement = useRef(null);
    
        // Definition von Methoden,
        // die von außen aufrufbar sein sollen.
        useImperativeHandle(ref, () => {
    
            // Fokus setzen
            focusInput: () => {
                refInputElement.current.focus();
            },
    
            // Wert zurücksetzen
            clearInput: () => {
                setValue('');
                refInputElement.current.focus();
            },
    
            // Wert abrufen
            getInputValue: () => {
                return inputValue;
            },
    
            // Spezifischen Wert setzen
            setInputValue: (newValue) => {
                setInputValue(newValue);
            }
    
        });
    
        return (
            <div style={{
                padding: 20,
                boxSizing: 'border-box',
                marginBottom: 20,
                backgroundColor: '#ffffff'
            }}>
                <h3>Kind-Komponente (Eingabefeld)</h3>
                <input
                    type="text"
                    ref={refInputElement}
                    value={inputValue}
                    onChange={(e) => setInputValue(e.target.value)}
                    placeholder="Gib etwas ein ..."
                    style={{
                        padding: 10,
                        boxSizing: 'border-box',
                        fontSize: 14,
                        border: '2px solid #cccccc',
                        marginBottom: 10,
                        widht: '100%'
                    }}
                />
                <div style={{
                    padding: 10,
                    boxSizing: 'border-box',
                    backgroundColor: 'lightblue'
                }}>
                    <span>Aktueller Wert: <strong style={{ color: green }}>{value}</strong></span>
                </div>
            </div>
        );
    
    }
    
    export default ChildComponent;

    Nun bauen wir die Eltern-Komponente auf, welche alle Buttons für die Steuerung des Eingabefeldes in der Kind-Komponente beinhaltet.

    ParentComponent.jsx
    import { useRef } from 'react';
    import ChildComponent from './ChildComponent';
    
    function ParentComponent() {
    
        const refSpecialInputElement = useRef();
    
        const handleFocusInput = () => {
            refSpecialInputElement.current.focusInput();
        };
    
        const handleClearInput = () => {
            refSpecialInputElement.current.clearInput();
        };
    
        const handleGetInputValue = () => {
            const currentValue = refSpecialInputElement.current.getInputValue();
            console.log(`Aktueller Wert: ${currentValue}`);
        };
    
        const handleSetInputValue = () => {
            refSpecialInputElement.current.setInputValue('Das ist ein Test-Wert');
        };
    
        return (
            <div
                className="app-wrapper"
                style={{
                    padding: 20,
                    border: '2px solid #aaaaaa',
                    borderRadius: 8,
                    boxSizing: 'border-box',
                    backgroundColor: '#eeeeee'
                }}
            >
                <h2>Eltern-Komponente (Steuerung)</h2>
    
                <ChildComponent ref={refSpecialInputElement} />
    
                <div
                    className="controls"
                    style={{
                        display: 'grid',
                        gridTemplateColumns: '1fr 1fr',
                        gridGap: 20
                    }}
                >
                    <button onClick={handleFocusInput}>
                        Fokus setzen
                    </button>
                    <button onClick={handleClearInput}>
                        Leeren
                    </button>
                    <button onClick={handleGetInputValue}>
                        Wert abrufen (Konsole)
                    </button>
                    <button onClick={handleSetInputValue}>
                        Wert setzen
                    </button>
                </div>
            </div>
        );
    
    }
    
    export default ParentComponent;

    Als Ergebnis haben wir eine Applikation, in welcher wir aus der Eltern-Komponente Funktionen in der Kind-Komponente aufrufen können.

    React Hook - useImperativeHandle - Beispiel 1