//
Busca en todas las páginas de la documentación
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Tipea correctamente useRef para referencias de elementos DOM y contenedores de valores mutables. Entiende la diferencia entre refs de solo lectura del DOM y refs mutables, y cuándo usar cada una.
// Ref de elemento DOM (current de solo lectura)
function TextInput() {
const inputRef = useRef<HTMLInputElement>(null);
const focusInput = () => {
inputRef.current?.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Enfocar entrada</button>
</div>
);
}// Ref mutable (current escribible)
function Timer() {
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
const [count, setCount] = useState(0);
const start = () => {
if (intervalRef.current) return;
intervalRef.current = setInterval(() => {
setCount((c) => c + 1);
}, 1000);
};
const stop = () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
};
return (
<div>
<p>{count}</p>
<button onClick={start}>Iniciar</button>
<button onClick={stop}>Detener</button>
</div>
);
}useRef<HTMLInputElement>(null) crea un objeto ref con { current: HTMLInputElement | null }. Cuando se pasa a un atributo JSX ref, React administra el establecimiento de .current al nodo del DOM.ref directamente en sus props sin forwardRef.null y tipea en consecuencia: useRef<NodeJS.Timeout | null>(null).useRef. La diferencia es si React administra .current (ref de DOM) o tú lo administras (ref mutable).Almacenar valor anterior:
function usePrevious<T>(value: T): T | undefined {
const ref = useRef<T | undefined>(undefined);
useEffect(() => {
ref.current = value;
});
return ref.current;
}Patrón de callback de ref:
function MeasuredBox() {
const [height, setHeight] = useState(0);
const measuredRef = (node: HTMLDivElement | null) => {
if (node) {
setHeight(node.getBoundingClientRect().height);
}
};
return (
<div ref={measuredRef}>
<p>Este cuadro tiene {height}px de alto</p>
</div>
);
}Ref de elemento de video:
const videoRef = useRef<HTMLVideoElement>(null);
// Reproducir/pausar
const togglePlay = () => {
if (videoRef.current?.paused) {
videoRef.current.play();
} else {
videoRef.current?.pause();
}
};HTMLDivElement, HTMLInputElement, HTMLButtonElement, HTMLFormElement, HTMLCanvasElement, HTMLVideoElement, SVGSVGElement.ReturnType<typeof setInterval> es portátil entre entornos Node y navegador en lugar de codificar NodeJS.Timeout o number.forwardRef ya no es necesario. Los componentes pueden aceptar ref como una prop normal: function Input({ ref }: { ref?: React.Ref<HTMLInputElement> }).inputRef.current sin una verificación de null generará un error en strictNullChecks. Siempre usa encadenamiento opcional (?.) o una guarda..current en una ref de DOM administrada por React no tiene efecto. React lo sobrescribe durante el renderizado.useRef<HTMLInputElement>(null!) (aserción de no-null) elimina la necesidad de verificaciones de null pero oculta errores potenciales si la ref se accede antes del montaje.null cuando el componente se desmonta. Siempre maneja el caso null.| Enfoque | Pros | Contras |
|---|---|---|
useRef<T>(null) | Seguro, manejo explícito de null | Requiere verificaciones de null en todas partes |
useRef<T>(null!) | Sin verificaciones de null necesarias | No seguro si se accede antes del montaje |
| Función de callback de ref | Se ejecuta en montaje/desmontaje, útil para mediciones | Más complejo, se dispara en cada renderizado en React 18 |
React.createRef() | Compatible con componentes de clase | Crea una ref nueva cada renderizado en componentes de función |
ref como prop (React 19) | No se necesita envoltorio forwardRef | Solo disponible en React 19+ |
ref y React administra .current (estableciéndola al nodo del DOM)..current tú mismo (p. ej., almacenando una ID de temporizador o un valor anterior).useRef. La diferencia es quién escribe en .current.null porque el nodo del DOM no existe hasta que el componente se monta.useRef<HTMLInputElement>(null) proporciona el tipo HTMLInputElement | null, que coincide con este ciclo de vida.const videoRef = useRef<HTMLVideoElement>(null);HTMLVideoElement como el parámetro de tipo.videoRef.current?.play() con encadenamiento opcional.setInterval, que difiere entre Node (NodeJS.Timeout) y navegadores (number).ReturnType<typeof setInterval> es portátil entre ambos entornos sin codificar.ref: ref={(node) => { ... }}.null).ref es una prop normal. Los componentes pueden aceptarla directamente:function Input({ ref }: { ref?: React.Ref<HTMLInputElement> }) { ... }forwardRef todavía funciona pero ya no es necesario.inputRef.current será null antes del montaje.useRef<HTMLInputElement>(null!) para omitir verificaciones de null, ocultas este error.?.) o una guarda de null en código de producción..current durante el renderizado.useRef<T | undefined>(undefined).useEffect actualiza ref.current después de cada renderizado, por lo que el valor devuelto siempre está un renderizado atrás.null: (node: HTMLDivElement | null) => void.null ya que el callback se dispara con null en el desmontaje.HTMLDivElement, HTMLInputElement, HTMLButtonElement, HTMLFormElementHTMLCanvasElement, HTMLVideoElement, SVGSVGElementnull.Revisado por Chris St. John·Última actualización: 7 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥