React TypeError: Cannot read properties of null (reading 'useRef')
Este error explota cuando se llama a un Hook de React fuera del contexto de un componente funcional, o cuando el módulo de React no está correctamente resuelto a una única instancia. El runtime trata React como null y no puede acceder a su propiedad useRef.
El Problema
// ❌ Bad Code — lib/focusHelper.js
// Se importa y se llama useRef FUERA de un componente React
import { useRef } from 'react';
// Función utilitaria normal, NO un componente ni un hook custom
export function createFocusRef() {
const ref = useRef(null); // ← Rompe las Reglas de los Hooks
return ref;
}
// En el componente:
import { createFocusRef } from './focusHelper';
export default function InputField() {
const inputRef = createFocusRef(); // TypeError aquí
return <input ref={inputRef} />;
}
Error en consola:
TypeError: Cannot read properties of null (reading 'useRef')
at Object.useRef (react.development.js:1571)
at createFocusRef (focusHelper.js:5)
La Solución
// ✅ Good Code — lib/focusHelper.js
// La lógica auxiliar solo acepta una ref ya creada, no la crea ella misma
export function focusElement(ref) {
if (ref?.current) {
ref.current.focus();
}
}
// En el componente — useRef se llama DENTRO del componente
import { useRef } from 'react';
import { focusElement } from './focusHelper';
export default function InputField() {
const inputRef = useRef(null); // ✅ Dentro del componente
return (
<input
ref={inputRef}
onFocus={() => focusElement(inputRef)}
/>
);
}
Por qué funciona
Las Reglas de los Hooks de React exigen que useRef (y cualquier otro Hook) se invoque únicamente en el nivel superior de un componente funcional o de un Hook personalizado (useXxx). Cuando se llama desde una función normal, React pierde el contexto de la fibra actual y devuelve null como dispatcher, provocando el TypeError. La solución es mover la creación de la ref al cuerpo del componente y pasar la ref ya instanciada a las funciones helper que la necesiten. Si la lógica es compleja y reutilizable, la alternativa correcta es convertirla en un custom Hook (useFocusRef) que sí puede contener Hooks internamente.