React 19 de Cero a Experto / Efectos y ciclo de vida
Custom hooks: empaqueta tu propia lógica
Fíjate en lo que se repite: el patrón de carga de datos, el de leer/escribir localStorage, el de
un toggle. Copiar y pegar esa lógica en cada componente es justo lo que el SC-02 te enseñó a
evitar. Los CUSTOM HOOKS son la respuesta de React: empaquetar lógica con estado y efectos en una
función reutilizable que empieza por use. No es magia ni una API nueva —es una función normal que
llama a otros hooks—. Hoy construyes los tuyos desde cero y entiendes por qué son el corazón de la
reutilización en React.
Una receta que guardas y reúsas
Tu primer custom hook: useLocalStorage
Un hook propio es una función que empieza por use y USA otros hooks por dentro. Aquí encapsulamos
"un estado que se persiste en localStorage":
useLocalStorage devuelve la misma tupla [valor, setValor] que useState —por eso se USA igual—,
pero por dentro añade la persistencia con un efecto. Fíjate: lo llamas DOS veces (para nombre y
para tema) y cada uno tiene su propio estado independiente. Un custom hook no comparte estado
entre usos: cada llamada es una instancia fresca. Es genérico (<T>, SC-03), así que sirve para
cualquier tipo. Escribiste la receta una vez; ahora persistir cualquier valor es una línea.
Las reglas de los hooks
Otro ejemplo: componer hooks
Los custom hooks se componen: uno puede usar a otro. Aquí useContador encapsula la lógica de un
contador con límites, sin tocar el DOM ni saber nada de la UI:
function useContador(inicial = 0, paso = 1) {
const [cuenta, setCuenta] = useState(inicial);
const incrementar = () => setCuenta((c) => c + paso);
const decrementar = () => setCuenta((c) => c - paso);
const reiniciar = () => setCuenta(inicial);
// devolvemos un objeto: la UI solo usa lo que le sirve
return { cuenta, incrementar, decrementar, reiniciar };
}
// en el componente:
function App() {
const { cuenta, incrementar, reiniciar } = useContador(0, 5);
return (
<>
<p>{cuenta}</p>
<button onClick={incrementar}>+5</button>
<button onClick={reiniciar}>Reiniciar</button>
</>
);
}useContador no sabe NADA de botones ni de estilos: solo expone estado (cuenta) y acciones
(incrementar, etc.). El componente decide cómo pintarlo. Esa separación —lógica en el hook, UI en
el componente— es lo que hace testeable y reutilizable tu código. Puedes usar useContador en diez
pantallas distintas, cada una con su propio look.
¿Qué es exactamente un custom hook y qué lo distingue de una función normal?
Mini-reto
Construye dos hooks propios: 1) useToggle(inicial = false) que devuelva [valor, alternar]
(usa useState y una función que haga setValor(v => !v)); úsalo para mostrar/ocultar un panel.
2) useAnterior(valor) que use un useRef y un useEffect para recordar el valor del render
ANTERIOR (guarda valor en el ref DESPUÉS del render, y devuelve ref.current); muéstralo junto
al valor actual. Confirma que ambos se usan como cualquier hook y que su lógica queda fuera del
componente.
Qué sigue
Módulo 3 casi cerrado: dominas los efectos (y cuándo NO usarlos), useRef, la carga de datos y los
custom hooks. El reto del módulo junta todo en una "Mi Bolsillo" que PERSISTE: tus gastos se
guardan en localStorage con un custom hook y sobreviven a recargas —el mismo salto de "app con
memoria" del SC-02, ahora en React declarativo—.