Werte, die nicht gerendert werden
Ein Ref kann jeden beliebigen Wert halten, nicht nur ein Element. Stell es dir als eine Kiste vor, die React für die Komponente von einem Rendern zum nächsten aufbewahrt: Du legst etwas in ref.current, und beim nächsten Rendern ist es noch da. Und anders als bei State löst eine Änderung von ref.current kein neues Rendern aus.
Das passt genau für Dinge, die dein Code braucht, die die Seite aber nicht zeigt. Ein typisches Beispiel ist die ID eines Intervalls, das ein Klick startet und ein anderer stoppt:
const intervalRef = useRef(null);
function starten() {
intervalRef.current = setInterval(() => {
setSekunden((sekunden) => sekunden + 1);
}, 1000);
}
function stoppen() {
clearInterval(intervalRef.current);
}Warum nicht etwas anderes?
- Eine normale Variable,
let intervalId;in der Komponente, überlebt kein Rendern. Bei jedem Rendern ruft React die Funktion der Komponente neu auf, und sie beginnt mit einer neuen, leerenintervalId. Eine Sekunde später hat das Intervall die Zeit geändert, die Komponente wurde neu gerendert, und die ID ist weg: Stopp hat nichts mehr zu stoppen. - State würde die ID behalten, aber jede Änderung von State rendert neu, und die Seite zeigt die ID gar nicht an.
Also: State für das, was die Seite zeigt, ein Ref für das, was nur dein Code braucht.
In der Stoppuhr hat ein Effekt das Intervall gestartet, sobald die Stoppuhr zu laufen begann, und die Aufräumfunktion hat es gestoppt. Hier starten und stoppen die Klick-Handler das Intervall selbst, deshalb muss seine ID zwischen den beiden Klicks irgendwo warten.
So schreibst du es:
Anweisungen
- 1
Erstelle
intervalRefmituseRef(null). Starte instartenein Intervall, das alle 1000 Millisekundensekundenum 1 erhöht, und speichere seine ID inintervalRef.current. - 2
Stoppe in
stoppendas Intervall mitclearInterval(intervalRef.current). - 3
Klicke zweimal auf Start: Es laufen zwei Intervalle, die Zeit steigt pro Sekunde um 2, und Stopp stoppt nur das zweite. Sorge dafür, dass ein zweiter Klick auf Start nichts tut: Beende
startengleich am Anfang mitreturn, wennintervalRef.currentnichtnullist. Und setze instoppenintervalRef.currentwieder aufnull, damit Start nach Stopp wieder funktioniert.