Librerías: React Hook Form y TanStack Form
Una vez entendido que un formulario es un gestor de estado especializado, las librerias dejan de parecer atajos y se revelan como lo que son: dos respuestas distintas al mismo problema de domar cinco dimensiones ortogonales sin repintar el mundo en cada tecla. React Hook Form parte del modelo no controlado —registra los campos con `ref`— y gana su velocidad legendaria suscribiendo cada componente solo a los campos que lee, de modo que teclear en uno no repinta los demas; integra la validacion por esquema con un resolver como `zodResolver`. TanStack Form ataca desde otro angulo: headless y agnostico del framework, prioriza la seguridad de tipos de extremo a extremo, infiriendo el tipo de cada campo desde los valores por defecto y los validadores, con suscripciones granulares campo a campo. Esta leccion contrasta que resuelve cada una y por que sus filosofias —rendimiento por no control frente a portabilidad type-safe— responden a prioridades distintas.
Despues de tres lecciones sabes que un formulario concentra cinco dimensiones ortogonales, que la eleccion entre controlado y no controlado decide su coste, y que la validacion se declara como un contrato. Con ese marco, las librerias de formularios dejan de ser cajas negras y se leen como decisiones de diseño explicitas sobre esos mismos ejes. React Hook Form y TanStack Form son las dos referencias de 2026, y lo interesante no es cual es “mejor”, sino que cada una optimiza una prioridad distinta: la primera exprime el rendimiento apoyandose en el modelo no controlado y en suscripciones quirurgicas; la segunda persigue la seguridad de tipos absoluta y la portabilidad entre frameworks a costa de un poco mas de ceremonia. Entender por que eligieron caminos opuestos vale mas que memorizar sus APIs, porque las APIs cambian y las prioridades de diseño perduran.
- Leer las librerias de formularios como gestores de estado especializados que automatizan las cinco dimensiones de la leccion uno.
- Explicar por que React Hook Form es rapido: modelo no controlado con
refmas suscripciones por campo que evitan el re-render global. - Entender la apuesta de TanStack Form: headless, agnostico del framework y seguro de tipos de extremo a extremo.
- Elegir entre ambas segun tus prioridades reales de rendimiento, portabilidad y garantias del compilador.
React Hook Form: velocidad por no controlar
React Hook Form toma la decision de la leccion dos y la lleva hasta el final: por defecto los campos son no controlados. En lugar de pasar value y onChange, registras cada campo con la funcion register, que conecta el nodo del DOM mediante una ref. El valor vive en el DOM, la libreria no repinta nada mientras el usuario teclea, y solo recoge los valores cuando de verdad los necesita, casi siempre al enviar. De ahi sale su rendimiento: en un formulario grande, escribir en un campo no dispara el render de los demas.
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
function Registro() {
const { register, handleSubmit, formState } = useForm({
resolver: zodResolver(esquemaRegistro), // el esquema de la leccion 3
});
const onSubmit = (datos) => guardar(datos);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("email")} />
{formState.errors.email && <span>{formState.errors.email.message}</span>}
<button disabled={formState.isSubmitting}>Enviar</button>
</form>
);
}
Dos detalles condensan su filosofia. El primero es el resolver: en lugar de reinventar la validacion, React Hook Form delega en el esquema de la leccion anterior a traves de zodResolver, de modo que el contrato de Zod sigue siendo la unica fuente de verdad. El segundo es formState, un objeto que expone ya calculadas las cinco dimensiones —errors, isDirty, touchedFields, isSubmitting, isValid— que en la leccion uno tuvimos que llevar a mano. La libreria es, literalmente, ese gestor de estado especializado que anticipamos.
Se suele resumir React Hook Form como rapido por ser no controlado, pero el no control es solo la mitad. La otra mitad es que formState es un objeto suscribible: un componente que lee formState.errors.email se re-renderiza solo cuando cambia el error de ese campo, no cuando cambia cualquier cosa del formulario. Para conectar componentes controlados de una libreria de UI, Controller crea una isla controlada dentro del modelo no controlado, aislando su render. La leccion profunda es la misma que viste con las signals: quien se suscribe a poco, se repinta poco. El rendimiento no viene de un truco, sino de leer con precision quirurgica solo el trozo de estado que cada componente necesita.
Conviene recordar de donde viene esta obsesion por el re-render. La generacion anterior de librerias, con Formik a la cabeza, era controlada de raiz: guardaba todos los valores en el estado de React y, en formularios grandes, cada tecla repintaba el mundo. React Hook Form nacio en buena medida como respuesta a ese dolor concreto, y por eso su bandera es el rendimiento y su medio es el modelo no controlado. Leerla sin ese contexto es perderse por que tomo las decisiones que tomo; leerla con el, se entiende que no es una preferencia estetica sino la correccion deliberada de un problema medido.
Ese linaje explica tambien su ergonomia: register es deliberadamente escueto porque cada tecla no debe pagar peaje, y el coste en tamaño de bundle se mantiene bajo porque la libreria hace poco en tiempo de render. Cuando la compares con TanStack Form, no midas solo lineas de codigo: mide tambien cuanto trabajo hace cada una mientras el usuario escribe, que es donde se juega la sensacion de fluidez.
TanStack Form: seguridad de tipos y portabilidad
TanStack Form parte de otra prioridad. Su obsesion no es exprimir el ultimo render, sino ofrecer seguridad de tipos de extremo a extremo y funcionar igual en React, Vue, Solid o Angular, porque su nucleo es agnostico del framework y headless: no trae ningun componente pintado, solo la logica del estado, y tu decides como se ve. El tipo de cada campo no se declara: se infiere de los valores por defecto y de los validadores, de modo que el compilador conoce el nombre y el tipo exacto de cada campo y te protege al leerlos.
import { useForm } from "@tanstack/react-form";
function Registro() {
const form = useForm({
defaultValues: { email: "", password: "" }, // de aqui se infieren los tipos
onSubmit: async ({ value }) => guardar(value),
});
return (
<form onSubmit={(e) => { e.preventDefault(); form.handleSubmit(); }}>
<form.Field
name="email"
children={(field) => (
<input
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
/>
)}
/>
</form>
);
}
El componente Field es el corazon del diseño: recibe un name con tipado estricto y expone, mediante una funcion hija, el estado de ese campo —su valor, sus errores, su meta— y sus manejadores. Cada Field se suscribe solo a su porcion del estado, asi que la granularidad del re-render la controlas tu, campo a campo. Es el mismo principio de suscripcion fina de React Hook Form, pero expresado de forma explicita y portable en lugar de resuelto por dentro.
La validacion en TanStack Form vive en cada Field y en el propio formulario, y es agnostica del validador: puedes colgar una funcion a mano o adaptar un esquema de Zod, Valibot u otro, tanto para reglas sincronas como asincronas, con control fino de cuando disparar cada una. Esa neutralidad es coherente con su filosofia: igual que no impone framework ni componentes, tampoco impone libreria de validacion, y se limita a orquestar el estado dejandote elegir cada pieza. A cambio de esa libertad y de sus tipos impecables, pide algo mas de codigo por campo que el register compacto de React Hook Form.
Dos filosofías para el mismo problema
Puestas una al lado de la otra, las dos librerias no compiten por el mismo hueco: responden a preguntas distintas. React Hook Form optimiza el caso mayoritario de React —muchos campos, prioridad al rendimiento, ecosistema maduro de resolvers y componentes— apoyandose en el modelo no controlado. TanStack Form optimiza para equipos que valoran las garantias del compilador por encima de todo y para bases de codigo que viven en varios frameworks a la vez, aceptando algo mas de verbosidad a cambio de tipos impecables y portabilidad.
React Hook Form
No controlado por defecto con register y ref. Rapido por diseño y con suscripcion por campo. Integra Zod via zodResolver y usa Controller para componentes controlados. La opcion pragmatica en React.
TanStack Form
Headless, agnostico del framework y con inferencia de tipos de extremo a extremo desde defaultValues. Suscripcion explicita con Field. La opcion para type-safety maxima y codigo portable entre frameworks.
Ambas resuelven ademas el caso que mas sufre el modelo ingenuo: los campos dinamicos, esas listas donde el usuario añade y quita filas —telefonos, invitados, lineas de un pedido—. React Hook Form lo cubre con useFieldArray y TanStack Form con un modo de array en su Field, y en los dos casos la gracia es que el estado de la lista, la validacion de cada fila y su identidad estable para el render los gestiona la libreria, no un useState de array que tendrias que sincronizar a mano con sus errores. Es, de nuevo, la leccion uno: mas dimensiones ortogonales que alguien tiene que rastrear sin abrir la puerta a estados imposibles.
Las dos, por ultimo, exponen ya modelada la maquina de envio que protagonizara la proxima leccion: un isSubmitting o un isPending que conectas al boton, y ganchos de exito y de error donde enchufar la mutacion y los mensajes del servidor. Y las dos se acoplan a las librerias de componentes visuales —React Hook Form con Controller, TanStack Form con la funcion hija de Field— tendiendo el puente entre su nucleo eficiente y los campos controlados que un sistema de diseño impone. No sustituyen a tu interfaz: se enganchan a ella dejando que tu decidas como se ve cada campo.
Lo que ninguna de las dos reinventa es la validacion: ambas delegan en esquemas como los de la leccion tres a traves de adaptadores, porque el contrato debe seguir siendo unico. Y lo que las dos resuelven es exactamente el trabajo que en la leccion uno tuvimos que hacer a mano: rastrear valores, touched y dirty, calcular errores derivados, gestionar la maquina de envio y —esto es lo que justifica su existencia— hacerlo sin repintar el formulario entero en cada pulsacion.
Antes de instalar nada, conviene recordar que el peso de estas librerias se justifica por la complejidad, no por la costumbre. Un formulario de un solo campo —una casilla de busqueda, un interruptor, un unico correo para suscribirse— rara vez necesita mas que un useState controlado o un campo no controlado leido con FormData. La regla es proporcional: cuando las cinco dimensiones de la leccion uno empiezan a pesar de verdad —muchos campos, validacion cruzada, errores de servidor, rendimiento medible—, la libreria deja de ser sobreingenieria y pasa a ser la decision sensata. Meter React Hook Form para un solo campo es como montar un store global para un contador: la herramienta no esta mal, el problema no la pedia.
La forma perezosa de aprender librerias de formularios es memorizar register, Controller, Field y sus firmas hasta que la proxima version las cambie y haya que reaprenderlas. La forma que perdura es leer cada libreria como una respuesta a las tres lecciones anteriores. Preguntate donde vive el valor: React Hook Form dice en el DOM, y de ahi hereda su velocidad; TanStack Form te deja elegir, y de ahi su portabilidad. Preguntate como evita el re-render global: ambas con suscripcion fina, una por dentro y otra explicita. Preguntate quien valida: ninguna, las dos delegan en tu esquema. Cuando lees asi, cambiar de libreria deja de ser aprender de cero y pasa a ser reconocer las mismas decisiones con otros nombres, igual que en el nivel del genoma reconocias Redux bajo el disfraz de MVI. La eleccion practica se vuelve entonces honesta: si tu prioridad es rendimiento en React con un ecosistema enorme detras, React Hook Form; si es seguridad de tipos absoluta o vivir en varios frameworks, TanStack Form. Pero la eleccion importa menos que el criterio, porque el criterio sobrevive a las dos librerias y a las que vengan a sustituirlas.
- Monta el mismo formulario de registro en React Hook Form y en TanStack Form, y compara cuanto codigo pide cada uno para un caso identico.
- En la version de React Hook Form, conecta un contador de renders a un campo y comprueba que teclear en otro no lo dispara: la suscripcion fina en accion.
- Integra tu esquema de
Zoden ambas mediante su resolver o adaptador, y verifica que ninguna te ha obligado a reescribir las reglas de validacion. - En TanStack Form, provoca un error de tipos escribiendo mal el
namede un campo y observa como el compilador te frena antes de ejecutar. - Enumera, para un proyecto tuyo, tres prioridades reales —rendimiento, tipos, portabilidad, ecosistema— y ordena las dos librerias segun cual sirve mejor a cada una.
- Escribe en una frase que trabajo de la leccion uno te ha ahorrado la libreria, para tener claro por que la usas y no solo que usas.