Sobes.tech
Junior

Welche Hooks gibt es in React?

sobes.tech KI

Antwort von AI

In React, ab Version 16.8, ermöglichen Hooks funktionalen Komponenten, Zustände zu verwalten und Lebenszyklusmethoden zu verwenden, die zuvor nur Klassenkomponenten vorbehalten waren.

Hier sind die wichtigsten eingebauten Hooks:

  • useState: Ermöglicht das Hinzufügen eines internen Zustands zu einer funktionalen Komponente. Gibt ein Paar zurück: den aktuellen Zustand und eine Funktion zu seiner Aktualisierung.

    // Beispiel useState
    import React, { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0); // Initialisierung mit 0
    
      return (
        <div>
          <p>Sie haben {count} mal geklickt</p>
          <button onClick={() => setCount(count + 1)}>
            Klick mich
          </button>
        </div>
      );
    }
    
  • useEffect: Ermöglicht das Ausführen von Nebenwirkungen in funktionalen Komponenten. Ähnlich zu den Lebenszyklusmethoden von Klassenkomponenten (componentDidMount, componentDidUpdate, componentWillUnmount).

    // Beispiel useEffect
    import React, { useState, useEffect } from 'react';
    
    function Example() {
      const [count, setCount] = useState(0);
    
      // Wird nach jedem Render ausgeführt
      useEffect(() => {
        document.title = `Sie haben ${count} mal geklickt`;
      });
    
      // Wird nur beim ersten Render ausgeführt (leeres Abhängigkeitsarray)
      useEffect(() => {
        console.log('Komponente gemountet');
        return () => {
          console.log('Komponente unmounted'); // Cleanup-Funktion
        };
      }, []);
    
      // Wird bei Änderung von count ausgeführt
      useEffect(() => {
        console.log('Count hat sich geändert:', count);
      }, [count]);
    
      return (
        <div>
          <p>Sie haben {count} mal geklickt</p>
          <button onClick={() => setCount(count + 1)}>
            Klick mich
          </button>
        </div>
      );
    }
    
  • useContext: Ermöglicht das Abonnieren von Änderungen im React-Kontext. Nimmt ein Kontext-Objekt, erstellt mit React.createContext(), an.

    // Beispiel useContext
    import React, { useContext } from 'react';
    
    const ThemeContext = React.createContext('light'); // Erstellen des Kontexts
    
    function ThemedButton() {
      const theme = useContext(ThemeContext); // Verwendung des Kontexts
    
      return (
        <button className={theme}>
          Button im Thema {theme}
        </button>
      );
    }
    
    function App() {
      return (
        <ThemedButton />
      );
    }
    
  • useReducer: Alternative zu useState für die Verwaltung komplexerer Zustände, die mehrere Unterwerte enthalten oder bei denen der nächste Zustand vom vorherigen abhängt. Ähnlich zu den Reducern in Redux.

    // Beispiel useReducer
    import React, { useReducer } from 'react';
    
    const initialState = { count: 0 };
    
    function reducer(state, action) {
      switch (action.type) {
        case 'increment':
          return { count: state.count + 1 };
        case 'decrement':
          return { count: state.count - 1 };
        default:
          throw new Error();
      }
    }
    
    function Counter() {
      const [state, dispatch] = useReducer(reducer, initialState);
    
      return (
        <>
          Count: {state.count}
          <button onClick={() => dispatch({ type: 'increment' })}>+</button>
          <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
        </>
      );
    }
    
  • useCallback: Memoisiert eine Rückruffunktion. Gibt eine memoized Version der Callback-Funktion zurück, die nur bei Änderungen einer Abhängigkeit neu erstellt wird. Nützlich, um unnötige Neurenderings von Kindkomponenten bei Übergabe von Callbacks zu verhindern.

    // Beispiel useCallback
    import React, { useState, useCallback } from 'react';
    
    function Parent({ addTodo }) {
      const [count, setCount] = useState(0);
    
      const handleAddTodo = useCallback(() => {
        addTodo();
      }, [addTodo]); // Abhängigkeit von addTodo
    
      return (
        <>
          <button onClick={() => setCount(count + 1)}>
            Zähler erhöhen
          </button>
          <Child onAddItem={handleAddTodo} />
        </>
      );
    }
    
    function Child({ onAddItem }) {
      console.log('Child wird gerendert'); // Wird nur bei Änderung von onAddItem gerendert
      return <button onClick={onAddItem}>Element hinzufügen</button>;
    }
    
  • useMemo: Memoisiert einen berechneten Wert. Gibt einen memoized Wert zurück, der nur bei Änderungen einer Abhängigkeit neu berechnet wird. Nützlich für Performance bei teuren Berechnungen.

    // Beispiel useMemo
    import React, { useMemo, useState } from 'react';
    
    function expensiveCalculation(num) {
      console.log('Teure Berechnung läuft...');
      for (let i = 0; i < 1000000; i++) {
        num += 1;
      }
      return num;
    }
    
    function Example() {
      const [count, setCount] = useState(0);
      const [todos, setTodos] = useState([]);
    
      const calculation = useMemo(() => expensiveCalculation(count), [count]); // Abhängigkeit von count
    
      const addTodo = () => {
        setTodos(t => [...t, "Neues Todo"]);
      };
    
      return (
        <div>
          <div>
            <h2>Meine Todos</h2>
            {todos.map((todo, index) => (
              <p key={index}>{todo}</p>
            ))}
            <button onClick={addTodo}>Todo hinzufügen</button>
          </div>
          <hr />
          <div>
            Zähler: {count}
            <button onClick={() => setCount(c => c + 1)}>+</button>
            <h2>Teure Berechnung</h2>
            {calculation}
          </div>
        </div>
      );
    }
    
  • useRef: Ermöglicht das Erstellen eines mutablen Refs, das während des gesamten Lebenszyklus der Komponente erhalten bleibt. Wird häufig verwendet, um auf DOM-Elemente zuzugreifen oder beliebige mutable Werte zu speichern, die keine Neurenderings auslösen.

    // Beispiel useRef
    import React, { useRef, useEffect } from 'react';
    
    function TextInputWithFocusButton() {
      const inputEl = useRef(null); // Erstellen des Refs
    
      const onButtonClick = () => {
        // current zeigt auf das gemountete DOM-Element
        inputEl.current.focus();
      };
    
      return (
        <>
          <input ref={inputEl} type="text" /> // Ref zuweisen
          <button onClick={onButtonClick}>Fokus auf Eingabefeld</button>
        </>
      );
    }
    
  • useImperativeHandle: Konfiguriert den Instanz-Deskriptor, der dem Elternteil bei Verwendung von ref bereitgestellt wird. Erlaubt es dem Kind, bestimmte Methoden dem Elternteil offenzulegen. Wird zusammen mit forwardRef verwendet.

    // Beispiel useImperativeHandle
    import React, { useRef, useImperativeHandle, forwardRef } from 'react';
    
    const MyInput = forwardRef((props, ref) => {
      const inputRef = useRef();
    
      useImperativeHandle(ref, () => ({
        focusInput: () => {
          inputRef.current.focus();
        }
      }));
    
      return <input ref={inputRef} {...props} />;
    });
    
    function ParentComponent() {
      const inputRef = useRef();
    
      const handleFocus = () => {
        inputRef.current.focusInput(); // Aufruf der Methode des Kind-Components
      };
    
      return (
        <div>
          <MyInput ref={inputRef} />
          <button onClick={handleFocus}>Fokus durch Parent</button>
        </div>
      );
    }
    
  • useLayoutEffect: Ähnlich wie useEffect, aber wird synchron nach allen DOM-Mutationen ausgeführt. Nützlich zum Lesen von DOM-Daten oder Ausführen von Mutationen, die vor dem nächsten Browser-Render erfolgen müssen. Kann das Rendering blockieren.

    // Beispiel useLayoutEffect
    import React, { useLayoutEffect, useRef } from 'react';
    
    function Tooltip({ children, text }) {
      const ref = useRef(null);
    
      useLayoutEffect(() => {
        if (ref.current) {
          // Berechnungen basierend auf DOM vor dem Render
          const { top, height } = ref.current.getBoundingClientRect();
          console.log(`Element befindet sich bei ${top} mit Höhe ${height}`);
        }
      }, [children]);
    
      return (
        <span ref={ref} title={text}>
          {children}
        </span>
      );
    }
    
  • useDebugValue: Zeigt eine benutzerdefinierte Markierung für Hooks in den React DevTools an. Wird in benutzerdefinierten Hooks für Debugging-Zwecke verwendet.

    // Beispiel useDebugValue
    import React, { useState, useDebugValue } from 'react';
    
    function useFriendStatus(friendID) {
      const [isOnline, setIsOnline] = useState(null);
    
      // Zeigt 'Friend Status: Offline' oder 'Friend Status: Online' in den DevTools an
      useDebugValue(isOnline === true ? 'Online' : 'Offline');
    
      // ... Logik zum Abrufen des Freund-Status
    
      return isOnline;
    }
    
    function FriendListItem({ friend }) {
      const isOnline = useFriendStatus(friend.id);
    
      return (
        <li style={{ color: isOnline ? 'green' : 'black' }}>
          {friend.name} - {isOnline ? 'Online' : 'Offline'}
        </li>
      );
    }
    

Neben den eingebauten Hooks gibt es auch benutzerdefinierte Hooks. Das sind JavaScript-Funktionen, deren Namen mit "use" beginnen. Sie ermöglichen die Wiederverwendung von Zustandslogik zwischen Komponenten. Ein benutzerdefinierter Hook kann andere Hooks aufrufen.

// Beispiel für einen benutzerdefinierten Hook
import { useState, useEffect } from 'react';

function useWindowSize() {
  const [size, setSize] = useState([window.innerWidth, window.innerHeight]);

  useEffect(() => {
    const handleResize = () => {
      setSize([window.innerWidth, window.innerHeight]);
    };
    window.addEventListener('resize', handleResize);
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);

  return size;
}

function MyComponent() {
  const [width, height] = useWindowSize(); // Verwendung des benutzerdefinierten Hooks

  return (
    <p>Fenstergröße: {width}x{height}</p>
  );
}

Wichtig ist die Einhaltung der Hook-Regeln:

  1. Rufen Sie Hooks nur auf der obersten Ebene der React-Komponente oder eines benutzerdefinierten Hooks auf. Rufen Sie sie nicht innerhalb von Schleifen, Bedingungen oder verschachtelten Funktionen auf.
  2. Rufen Sie Hooks nur in React-Funktionskomponenten oder benutzerdefinierten Hooks auf. Rufen Sie sie nicht in normalen JavaScript-Funktionen oder Klassenmethoden auf.