Zum Inhalt springen
React Anfänger 20 min

useRef Hook

Lerne den useRef Hook kennen - für DOM-Zugriff und persistente Werte ohne Re-Render. Praktische Beispiele und Best Practices.

Aktualisiert:

useRef Hook

Der useRef-Hook gibt dir zwei Superkraefte: direkten Zugriff auf DOM-Elemente und die Moeglichkeit, Werte zu speichern, die keinen Re-Render ausloesen. Er ist das perfekte Werkzeug fuer Situationen, in denen useState zu viel des Guten waere.

Was ist useRef?

useRef erstellt ein Objekt mit einer current-Eigenschaft, die zwischen Renders bestehen bleibt:

import { useRef } from 'react';

function MyComponent() {
  const myRef = useRef(initialValue);

  // Wert lesen
  console.log(myRef.current);

  // Wert schreiben
  myRef.current = 'neuer Wert';
}

DOM-Elemente referenzieren

Der haeufigste Anwendungsfall: auf DOM-Elemente zugreifen:

function FocusInput() {
  const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();  // Direkt auf das DOM-Element zugreifen
  }

  return (
    <div>
      <input ref={inputRef} placeholder="Ich bekomme den Fokus..." />
      <button onClick={handleClick}>Input fokussieren</button>
    </div>
  );
}

Wie es funktioniert

1. useRef(null) erstellt { current: null }
2. React setzt ref={inputRef} → inputRef.current = <input>-Element
3. Du kannst inputRef.current wie ein normales DOM-Element nutzen

Weitere DOM-Beispiele

function ScrollToTop() {
  const topRef = useRef(null);

  function scrollToTop() {
    topRef.current.scrollIntoView({ behavior: 'smooth' });
  }

  return (
    <div>
      <div ref={topRef} />
      {/* Langer Inhalt */}
      <div style={{ height: '200vh' }}>Scroll nach unten...</div>
      <button onClick={scrollToTop}>Nach oben scrollen</button>
    </div>
  );
}
function VideoPlayer() {
  const videoRef = useRef(null);

  return (
    <div>
      <video ref={videoRef} src="/video.mp4" />
      <div>
        <button onClick={() => videoRef.current.play()}>Abspielen</button>
        <button onClick={() => videoRef.current.pause()}>Pause</button>
        <button onClick={() => { videoRef.current.currentTime = 0; }}>
          Zuruecksetzen
        </button>
      </div>
    </div>
  );
}

Werte speichern ohne Re-Render

Der zweite wichtige Anwendungsfall: Werte merken, ohne die Komponente neu zu rendern:

function RenderCounter() {
  const renderCount = useRef(0);

  // Bei jedem Render erhoehen - OHNE Re-Render auszuloesen
  renderCount.current += 1;

  return <p>Diese Komponente wurde {renderCount.current}x gerendert.</p>;
}

useState vs. useRef

useStateuseRef
Loest Re-Render ausJaNein
Wert bleibt zwischen RendersJaJa
Verwendung in JSXJaMoeglich, aber nicht reaktiv
Typischer EinsatzUI-StateDOM-Zugriff, Hilfswerte

Vorherigen Wert speichern

Ein nuetzliches Pattern – den vorherigen State-Wert merken:

function PreviousValue() {
  const [count, setCount] = useState(0);
  const prevCountRef = useRef(0);

  useEffect(() => {
    prevCountRef.current = count;
  }, [count]);

  return (
    <div>
      <p>Aktuell: {count}</p>
      <p>Vorher: {prevCountRef.current}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

Timer-IDs speichern

Perfekt fuer Timer und Intervalle:

function Stopwatch() {
  const [seconds, setSeconds] = useState(0);
  const [isRunning, setIsRunning] = useState(false);
  const intervalRef = useRef(null);

  function start() {
    if (isRunning) return;
    setIsRunning(true);
    intervalRef.current = setInterval(() => {
      setSeconds(prev => prev + 1);
    }, 1000);
  }

  function stop() {
    setIsRunning(false);
    clearInterval(intervalRef.current);
  }

  function reset() {
    stop();
    setSeconds(0);
  }

  // Cleanup beim Unmount
  useEffect(() => {
    return () => clearInterval(intervalRef.current);
  }, []);

  return (
    <div>
      <p style={{ fontSize: '2rem', fontFamily: 'monospace' }}>
        {String(Math.floor(seconds / 60)).padStart(2, '0')}:
        {String(seconds % 60).padStart(2, '0')}
      </p>
      <button onClick={start} disabled={isRunning}>Start</button>
      <button onClick={stop} disabled={!isRunning}>Stop</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

Praktisches Beispiel: Auto-Resize Textarea

function AutoResizeTextarea() {
  const textareaRef = useRef(null);
  const [text, setText] = useState('');

  function handleChange(e) {
    setText(e.target.value);

    const textarea = textareaRef.current;
    textarea.style.height = 'auto';
    textarea.style.height = textarea.scrollHeight + 'px';
  }

  return (
    <textarea
      ref={textareaRef}
      value={text}
      onChange={handleChange}
      placeholder="Schreibe etwas... Die Textbox waechst mit!"
      style={{
        width: '100%',
        minHeight: '50px',
        padding: '0.5rem',
        resize: 'none',
        overflow: 'hidden',
        borderRadius: '8px',
        border: '1px solid #ccc'
      }}
    />
  );
}

Wann useRef statt useState?

Verwende useRef wenn:

  • Du auf ein DOM-Element zugreifen musst
  • Du einen Wert speichern willst, der keinen Re-Render ausloesen soll
  • Du eine Timer-ID oder Interval-ID speichern musst
  • Du den vorherigen Wert eines States brauchst

Verwende useState wenn:

  • Der Wert in der UI angezeigt werden soll
  • Eine Aenderung einen Re-Render ausloesen soll

Uebungen

  1. Erstelle ein Formular, das automatisch das erste Eingabefeld fokussiert
  2. Baue eine Stoppuhr mit Start, Stop, Reset und Rundenzeiten
  3. Erstelle eine Komponente, die misst, wie lange der User auf der Seite ist

Was kommt als Naechstes?

Du kennst jetzt useRef fuer DOM-Zugriff und persistente Werte. Im naechsten Kapitel lernst du den useContext Hook – damit kannst du Daten ueber mehrere Komponentenebenen hinweg teilen, ohne Props durchzureichen.

Zusammenfassung

  • useRef erstellt eine persistente Referenz, die zwischen Renders bestehen bleibt
  • Hauptanwendungen: DOM-Zugriff und Werte ohne Re-Render speichern
  • Aenderungen an ref.current loesen keinen Re-Render aus
  • Ideal fuer Timer-IDs, vorherige Werte und DOM-Manipulationen
  • Verwende useState wenn der Wert die UI beeinflusst, useRef wenn nicht

Pro-Tipp: Nutze useRef nicht als Ersatz fuer useState, nur weil du Re-Renders vermeiden willst. Wenn ein Wert in der UI sichtbar sein soll, braucht er useState. Vorzeitige Optimierung macht den Code nur schwerer zu verstehen!

Zurück zum React Kurs