useRef — is een React hook die een muteerbaar ref-object creëert met de eigenschap .current, dat behouden blijft tussen renders van de component. In tegenstelling tot useState veroorzaakt het wijzigen van .current geen herrender, wat useRef ideaal maakt voor het opslaan van DOM-referenties, timers en alle waarden die renders moeten overleven zonder de UI opnieuw te tekenen. Volgens React Documentation (2025) wordt het ref-object één keer aangemaakt tijdens de levensduur van de component en verandert het niet tussen renders, wat de stabiliteit van de referentie garandeert.
Belangrijkste punten
useRef — is een hook die is toegevoegd in React 16.8 en een muteerbaar ref-object retourneert met één eigenschap .current. De beginwaarde wordt toegewezen aan .current bij het monteren van de component. Het belangrijkste verschil met een gewone variabele — het ref-object overleeft herrenders: bij een herrender maakt React de ref niet opnieuw aan, maar retourneert hetzelfde object.
De interne implementatie van useRef gebruikt hetzelfde mechanisme als useState en useEffect — een gelinkte lijst van hooks op de fiber-knoop. In tegenstelling tot useState houdt React echter geen wijzigingen van het ref-object bij, plaatst het geen updates in de wachtrij en plant het geen herrender. Dit maakt useRef een uiterst lichte hook die de prestaties niet beïnvloedt, zelfs niet bij frequente wijzigingen.
Volgens React Team — Hooks FAQ (2025) is useRef in wezen een “dos” die een waarde opslaat. Syntactische suiker: const ref = useRef(initialValue) is equivalent aan const ref = { current: initialValue } met het verschil dat React garandeert dat het ref-object bij elke render hetzelfde zal zijn. Geen magie — gewoon een stabiele referentie beheerd door React.
import { useRef } from 'react';
function Component() {
const countRef = useRef(0);
// countRef.current = 0 initieel
// countRef.current = 5 na mutatie
// Geen herrender vindt plaats!
}
Het meest voorkomende gebruiksscenario van useRef — het verkrijgen van directe toegang tot het DOM-element. React kent elementRef.current de referentie naar de DOM-knoop toe na het monteren van de component. Dit is nodig voor het focussen van een input, het meten van afmetingen van een element, integratie met animatiebibliotheken en bibliotheken die geen React-rendering gebruiken.
React beheert automatisch ref-referenties naar de DOM: bij montage wordt de werkelijke DOM-knoop toegewezen, bij demontage wordt deze gereset (null gezet). Dit garandeert dat .current altijd een actuele waarde bevat en voorkomt geheugenlekken via “slapende” verwijzingen naar verwijderde elementen. Er is geen handmatige opschoning nodig.
function AutoFocusInput() {
const inputRef = useRef(null);
useEffect(() => {
// Focus input na montage van component
inputRef.current?.focus();
}, []);
return <input ref={inputRef} type="text" />;
}
Volgens React — Refs and DOM documentation (2025), gebruik ref niet voor declaratieve bewerkingen — openen/sluiten van modals, zichtbaarheid beheren. Daarvoor bestaan state en props. Refs zijn bedoeld voor imperatieve bewerkingen die niet declaratief kunnen worden uitgedrukt: focus, tekstselectie, integratie met bibliotheken van derden.
Het tweede belangrijkste scenario — het opslaan van willekeurige waarden die tussen renders behouden moeten blijven, maar waarvan de wijziging geen herrender mag veroorzaken. Typische voorbeelden: timer-identificaties (setInterval/setTimeout), vlaggen voor het annuleren van verzoeken, vorige prop-waarden voor vergelijking en alle gegevens die de UI-uitvoer niet beïnvloeden.
Dit is vooral handig in useEffect: useRef slaat de timer-identificatie op en de cleanup verwijdert deze. Als timerId in useState wordt opgeslagen, zou elke aanroep van setTimerId een onnodige herrender veroorzaken die noch voor de logica noch voor de UI nodig is. useRef lost dit probleem op zonder overhead en zonder onnodig hertekenen.
function Timer() {
const intervalRef = useRef(null);
const start = () => {
intervalRef.current = setInterval(() => {
console.log('tik');
}, 1000);
};
const stop = () => {
clearInterval(intervalRef.current);
};
useEffect(() => stop, []);
return <><button onClick={start}>Start</button><button onClick={stop}>Stop</button></>;
}
Het belangrijkste dilemma — de keuze tussen useRef en useState — wordt opgelost met één vraag: “Is een herrender nodig bij wijziging van de waarde?”. Zo ja — useState. Zo nee — useRef. useState slaat de toestand op die de uitvoer van de component beïnvloedt; useRef slaat gegevens op die nodig zijn voor de interne logica, maar de UI niet beïnvloeden.
In de praktijk gebruiken ontwikkelaars vaak useRef om callbacks op te slaan, om problemen met closures te voorkomen. Als useEffect bijvoorbeeld abonneert op een gebeurtenis en binnen de callback de actuele state nodig is — sla de callback dan op in useRef. Werk bij elke render ref.current bij met de nieuwe functie en het effect zal altijd de verse callback aanroepen zonder herabonnering.
| Criterium | useRef | useState |
|---|---|---|
| Herrrender | Veroorzaakt geen bij wijziging | Veroorzaakt bij elke setState |
| Mutatie | Direct: ref.current = value | Via setter: setState(value) |
| Gebruik in JSX | Niet gebruikt (geen effect) | Gebruikt in uitvoer van component |
| Voorbeeld | Timers, DOM-referenties, vorige waarden | Formuliergegevens, UI-status, vlaggen |
Er bestaat een anti-pattern: useRef gebruiken om gegevens op te slaan die nodig zijn in JSX, maar waarvan de wijziging geen herrender mag veroorzaken. Dit leidt tot desynchronisatie — de UI toont oude gegevens, terwijl ref.current al nieuw is. Als de waarde in de UI wordt weergegeven — gebruik useState. Als deze alleen binnen de logica wordt gebruikt — useRef.
De combinatie useRef + useEffect — een standaard patroon voor het bijhouden van vorige prop-waarden. Sla de vorige waarde op in ref, vergelijk met de huidige in useEffect en neem een beslissing op basis van het verschil. Dit is vooral handig bij animaties, wanneer je moet weten welke waarde er vóór de wijziging was.
function PriceDisplay({ price }) {
const prevPriceRef = useRef(price);
useEffect(() => {
const prevPrice = prevPriceRef.current;
if (price > prevPrice) {
animateUp();
} else if (price < prevPrice) {
animateDown();
}
prevPriceRef.current = price;
}, [price]);
return <span>${price}</span>;
}
Volgens React Documentation — Hooks FAQ (2025) wordt dit patroon “previous value pattern” genoemd. Het werkt omdat useRef de waarde tussen renders behoudt en useEffect wordt uitgevoerd na bevestiging van de wijzigingen. Eerst wordt de DOM bijgewerkt met de nieuwe price, vervolgens vergelijkt useEffect met de vorige (die nog in ref staat) en werkt ref.current bij naar de huidige waarde.
De meest voorkomende fout — het lezen van ref.current in de renderfase voor het berekenen van JSX. Omdat het wijzigen van ref.current geen herrender veroorzaakt, kan de component een verouderde waarde gebruiken. Als de waarde van .current deelneemt aan de UI-uitvoer — gebruik useState. Als je ref en state moet synchroniseren, gebruik dan useEffect om de state vanuit ref bij te werken.
// ❌ Lees ref.current niet tijdens render voor weergave
function BadComponent() {
const valRef = useRef(0);
return <p>{valRef.current}</p>; // zal NIET worden bijgewerkt bij mutatie
}
// ✅ Gebruik state voor weergave, ref voor logica
function GoodComponent() {
const [val, setVal] = useState(0);
const valRef = useRef(0);
return <p>{val}</p>;
}
Een andere veelvoorkomende fout — het gebruik van useRef als de enige manier om toestand in de component op te slaan, wanneer de gegevens toch de UI beïnvloeden. Ontwikkelaars kiezen useRef om “onnodige” herrenders te voorkomen, maar krijgen uiteindelijk een UI die niet wordt bijgewerkt. De juiste aanpak: gebruik useState voor UI-gegevens en useRef alleen voor hulpwaarden die niet deelnemen aan het renderen.
Veelgestelde vragen
Ja, dit is een veelvoorkomend patroon — previous state pattern. Maak een ref en werk deze bij in useEffect bij elke wijziging van de gevolgde waarde. Op het moment tussen render en effect bevat ref.current de vorige waarde die kan worden vergeleken met de huidige. Dit vereist geen extra herrenders en werkt met alle gegevenstypen.
React kent ref.current de waarde van de DOM-knoop pas toe nadat het element is gerenderd en toegevoegd aan de echte DOM. Tijdens de eerste render is de component nog niet gemonteerd, daarom is ref.current gelijk aan de beginwaarde (null). Toegang tot DOM via ref.current is alleen mogelijk in useEffect of in gebeurtenis-handlers die na montage worden aangeroepen.
createRef maakt bij elke render een nieuw ref-object aan — dit mag alleen in class-componenten worden gebruikt. useRef maakt de ref één keer aan en retourneert hetzelfde object bij alle volgende renders. Gebruik in functionele componenten uitsluitend useRef; createRef leidt tot verlies van de waarde bij herrender, omdat het object opnieuw wordt aangemaakt.
Ja, het ref-object kan als een gewone prop worden doorgegeven: <Child inputRef={inputRef} />. De component gebruikt het via inputRef.current. Voor het direct doorgeven van ref aan het DOM-element van de kind-component gebruik je echter forwardRef — een HOC die het mogelijk maakt ref door props te laten gaan. Zonder forwardRef wordt ref niet automatisch gekoppeld aan het DOM-element binnen de kind-component.
Koppel ref aan het element, lees vervolgens in useEffect ref.current.getBoundingClientRect() of ref.current.offsetWidth / offsetHeight. Gebruik voor het reactief volgen van groottewijzigingen ResizeObserver binnen useEffect: maak een observer, abonneer op wijzigingen en werk state bij met de nieuwe afmetingen. Vergeet niet de observer uit te schakelen in de cleanup.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook