Anti-patrones de React · Code Review
Código que funciona, pasa los tests y parece limpio — y aún así está mal. Cada lección te entrega un componente para revisar: encontrás los problemas antes de leer el análisis, seguís la secuencia de ejecución que los causa, y decidís cuáles bloquearían el PR. Varias lecciones incluyen código que parece sospechoso y está bien: marcar código bueno también tiene un costo.
Este curso revisa código. El modelo — render vs commit, snapshots de estado, ciclo de vida de los effects, identidad, memoización — se enseña en React: Patrones, Buenas Prácticas e Internals. Cada lección de acá enlaza la lección de allá que necesitás.
Aprendamos juntos.
Pregúntame sobre este curso o por dónde empezar.
Qué causa un render, por qué el render tiene que ser puro, y por qué el estado que acabás de setear no es el que tenés en la mano.
- Paso 1Correctitud
¿Qué causa realmente un render?
El contador incrementa — un `console.log` demuestra que la variable sube — y la pantalla nunca cambia. No hay ...
Comenzar lección - Paso 2Correctitud
El render tiene que ser puro
Un componente escribe en `localStorage` y hace push a un arreglo de módulo mientras renderiza. En producción f...
Comenzar lección - Paso 3Correctitud
El estado es una instantánea
Un handler llama `setCount(count + 1)` tres veces y el contador sube uno. Después loguea `count` justo tras se...
Comenzar lección
Estado derivado, props copiadas al estado, booleanos que en realidad son una máquina de estados, estado demasiado arriba, estado duplicado, y mutación.
- Paso 4
Guardar estado derivado
Tres estados, y el tercero son los dos primeros pegados por un effect. Funciona, y renderiza dos veces por cad...
Comenzar lección - Paso 5CorrectitudDepende
Duplicar props en el estado
Un revisor abre un PR. El componente recibe una prop `name` y la copia al estado en la primera línea. Todo se ...
Comenzar lección - Paso 6Correctitud
Varios booleanos para una sola máquina de estados
Tres booleanos describen un pedido. Tres booleanos tienen ocho combinaciones; el pedido tiene cuatro estados....
Comenzar lección - Paso 7
Estado que debería ser local
La raíz de la app posee si un tooltip está abierto. Cada tecla en el buscador del tooltip re-renderiza la apli...
Comenzar lección - Paso 8Correctitud
Estado que debería ser compartido
Dos componentes guardan cada uno su copia de la moneda seleccionada. Arrancan iguales, así que parece bien, y ...
Comenzar lección - Paso 9Correctitud
Mutar el estado
Dos handlers cambian los datos correctamente y ninguno actualiza la pantalla. La consola demuestra que los obj...
Comenzar lección
Effects que calculan, effects que responden a clics, mentiras en las dependencias, bucles infinitos, dependencias inestables, limpieza faltante, y races.
- Paso 10
Usar Effects para calcular
Un effect filtra una lista al estado cada vez que la lista cambia. Es correcto, es una de las formas más comun...
Comenzar lección - Paso 11Correctitud
Usar Effects para responder a eventos del usuario
Hacer clic en *confirmar pedido* setea un flag; un effect observa el flag y manda el pedido. Funciona, y tiene...
Comenzar lección - Paso 12Correctitud
Mentirle al arreglo de dependencias
El effect lee `userId` y declara `[]`. La regla de lint se desactivó con un comentario explicando que sólo tie...
Comenzar lección - Paso 13Correctitud
Bucles infinitos de effects
Un effect setea un estado del que depende su propio arreglo de dependencias. El componente renderiza para siem...
Comenzar lección - Paso 14Correctitud
Objetos y funciones como dependencias
El effect se conecta a una sala de chat y depende de un objeto `options`. El objeto se construye en el render,...
Comenzar lección - Paso 15Correctitud
Falta la limpieza del effect
Tres effects arrancan algo que sobrevive al render: un listener, un interval y una suscripción. Ninguno devuel...
Comenzar lección - Paso 16Correctitud
Race conditions asíncronas
Hacé clic en Alice, Bob, Charlie rápido. Los pedidos vuelven en otro orden del que los pediste, y el panel ter...
Comenzar lección
Refs como estado escondido, refs para esquivar renders, y el DOM que React cree suyo — más los casos donde cada una de esas cosas es correcta.
- Paso 17Correctitud
Usar un ref como estado escondido
Un formulario guarda su borrador en un ref porque «escribir no debería re-renderizar todo». El input funciona ...
Comenzar lección - Paso 18Depende
Envolver el estado en un ref para evitar renders
Este componente guarda el mismo valor en un estado y en un ref, y lee el que le conviene. Ese patrón es legíti...
Comenzar lección - Paso 19CorrectitudDepende
Manipular DOM que React posee
Un handler setea `textContent` y `style.color` directo en un nodo que renderizó React. Funciona — hasta el pró...
Comenzar lección
El componente que creció, el que no debería existir, prop drilling versus abuso de context, el provider dios, y hooks que sólo renombran React.
- Paso 20
El componente gigante
Un componente hace fetch, filtra, ordena, renderiza una tabla, posee un modal, posee un formulario, chequea pe...
Comenzar lección - Paso 21
Sobre-componentización
Siete componentes renderizan una línea de texto. Cada uno es una función pura que toma props y devuelve JSX — ...
Comenzar lección - Paso 22Depende
Prop drilling vs abuso de Context
Un valor se pasa tres niveles como prop, y un revisor pidió moverlo a context. A veces eso está bien. Acá no....
Comenzar lección - Paso 23
El provider de context gigante
Un provider guarda el usuario, el tema, el carrito, los filtros y un flag de modal. Escribir en el buscador re...
Comenzar lección - Paso 24Depende
Custom hooks prematuros
Tres custom hooks. Uno se gana su nombre; los otros dos son React escrito distinto....
Comenzar lección
Keys por índice, keys aleatorias, y usar una key a propósito para reiniciar un subárbol — el mismo mecanismo produciendo un bug, un desastre y una técnica.
- Paso 25CorrectitudDepende
Usar el índice del arreglo como key
QA reporta: «borrar una tarea mueve los tildes a las tareas equivocadas». El borrado es correcto. El estado es...
Comenzar lección - Paso 26Correctitud
Keys aleatorias
Un usuario reporta: «no puedo escribir en el buscador — pierde el foco con cada letra». Alguien había agregado...
Comenzar lección - Paso 27Depende
Usar una key a propósito para reiniciar el estado
El mismo mecanismo de las dos lecciones anteriores, usado a propósito. Cambiar de usuario debería descartar el...
Comenzar lección
useMemo en todos lados, useCallback en todos lados, memo en todos lados, qué cambia el React Compiler, y trabajo caro por razones que la memoización no toca.
- Paso 28
useMemo en todos lados
Seis memos en un componente. Cinco envuelven aritmética o concatenación; uno envuelve un orden O(n log n) real...
Comenzar lección - Paso 29Depende
useCallback en todos lados
Cuatro callbacks, todos envueltos. Dos se entregan a un hijo envuelto en `memo` o se usan como dependencia de ...
Comenzar lección - Paso 30
React.memo en todos lados
Todos los componentes de este archivo están envueltos en `memo`. Hacé clic en el contador y mirá cuántos re-re...
Comenzar lección - Paso 31Depende
El React Compiler y la memoización manual
«El compiler memoiza todo, así que podemos borrar esto». Esa frase es medio cierta, y la mitad incorrecta muer...
Comenzar lección - Paso 32
Trabajo caro en el render
Un componente filtra, ordena y mapea un dataset grande en cada render — incluida cada tecla en un input no rel...
Comenzar lección
Actualizaciones de estado a frecuencia de puntero, layout medido en cada movimiento, y cincuenta mil nodos del DOM — tres costos que no son de React.
- Paso 33Depende
Actualizar estado en eventos de puntero de alta frecuencia
Una interacción de arrastre guarda la posición del puntero en el estado en cada `pointermove`. Es la forma más...
Comenzar lección - Paso 34
Medir el layout una y otra vez
Un handle de resize lee `getBoundingClientRect()` en cada movimiento del puntero, y otra vez adentro de un `us...
Comenzar lección - Paso 35Depende
Renderizar listas enormes sin virtualización
Una lista renderiza todas sus filas. Con 20 filas es correcto y simple. Con 5 000 son 5 000 nodos del DOM que ...
Comenzar lección
El booleano de carga, estado del servidor modelado como estado del cliente, y los tres desenlaces que nadie diseña.
- Paso 36Correctitud
El booleano de carga en todos lados
`isLoading` arranca como un booleano y le crece un segundo para errores, después un tercero para «ya cargó alg...
Comenzar lección - Paso 37Correctitud
Traer datos del servidor como si fueran estado local
Dos componentes piden el mismo usuario al montar. Los datos se guardan en `useState`, así que ninguno sabe que...
Comenzar lección - Paso 38Correctitud
Ignorar la UX de carga, vacío y error
El componente renderiza el camino feliz. Los otros tres desenlaces son lo que salga: un destello de «sin resul...
Comenzar lección
Controlado por defecto sin preguntarse por qué, effects cableados entre campos, y el estado de formulario en un objeto que re-renderiza todo.
- Paso 39Depende
Hacer todo controlado sin una razón
Doce campos, doce estados, doce handlers `onChange`. Cada tecla en cualquier campo re-renderiza todo el formul...
Comenzar lección - Paso 40Correctitud
Sincronizar el estado del formulario con effects
Cuatro effects cablean campos entre sí: la cantidad alimenta el subtotal, el subtotal el impuesto, el impuesto...
Comenzar lección - Paso 41CorrectitudDepende
El objeto gigante de estado del formulario
Un `useState` guarda todos los campos, y cada cambio esparce el objeto entero. Es la forma de formulario más c...
Comenzar lección
Reducers que mutan, reducers que copian lo que no cambió, stores externos leídos sin suscribirse, y todo en el estado global.
- Paso 42Correctitud
useReducer mal usado
El reducer hace push a `state.items` y devuelve `state`. Despachar no hace nada visible — y después un dispatc...
Comenzar lección - Paso 43
Reducers que copian lo que no cambió
Este reducer es escrupulosamente inmutable — reconstruye cada objeto anidado en cada acción, incluidos los que...
Comenzar lección - Paso 44Correctitud
Stores externos sin suscripción
Un store a nivel de módulo guarda el carrito. Los componentes leen `store.items` durante el render y llaman `s...
Comenzar lección - Paso 45Depende
Poner todo en el estado global
Un store guarda el usuario logueado, el tema — y también si un dropdown está abierto y qué escribió el usuario...
Comenzar lección
Costumbres viejas que dejaron de ser necesarias, Actions, UI optimista que puede perder, Suspense como funciona de verdad, y la frontera del servidor.
- Paso 46Depende
Patrones viejos usados por costumbre
Cuatro costumbres de React viejo, todas todavía funcionan, todas todavía se escriben por memoria muscular. Dos...
Comenzar lección - Paso 47Correctitud
Malentender las Actions
Un formulario lleva `isPending` a mano, deshabilita su botón, atrapa sus errores y resetea sus campos. React 1...
Comenzar lección - Paso 48Correctitud
UI optimista mal hecha
El botón de like se actualiza al instante y nunca lo deshace. Hacé fallar el pedido y el conteo queda mal hast...
Comenzar lección - Paso 49CorrectitudDepende
Suspense como envoltorio de spinner
Un componente envuelve a un hijo en `<Suspense>` y espera que React aguarde el `fetch` de adentro. React no lo...
Comenzar lección - Paso 50Depende
Responsabilidad del servidor vs del cliente
Esta lección es específica del framework y no corre acá: los React Server Components necesitan un bundler y un...
Comenzar lección
Cinco componentes con varios problemas independientes cada uno. Encontralos antes del análisis — y en el Lab 3, acertá con los dos que están bien.
- Paso 51Correctitud
Lab 1 — Buscador de usuarios
Un buscador que consulta una API mientras escribís. Salió a producción y casi siempre funciona — justo el tipo...
Comenzar lección - Paso 52Correctitud
Lab 2 — Carrito de compras
Un carrito que agrega ítems, cambia cantidades y muestra un total. El reporte dice: «a veces la cantidad no se...
Comenzar lección - Paso 53Depende
Lab 3 — Dashboard, y el código que sólo parece malo
Tres de las cosas en este componente merecen un comentario de PR. Dos están bien, y una de esas dos es del tip...
Comenzar lección - Paso 54
Lab 4 — Tablero de arrastrar y soltar
Un tablero con tarjetas arrastrables. Va fluido con tres tarjetas y se traba con sesenta, en una máquina que n...
Comenzar lección - Paso 55Correctitud
Lab 5 — Formulario asíncrono
Un formulario que envía un comentario. Tiene un booleano de carga, un effect que dispara el pedido, y UI optim...
Comenzar lección
Una feature, doce cosas que merecen opinión, nueve de las cuales son problemas. Escribí la revisión antes de escribir código.
Las reglas por categoría y los cuatro árboles de decisión, escritos para reabrirse durante una revisión y no para memorizarse una vez.
- Paso 57Depende
Referencia — Las reglas, por categoría
Once categorías, cada una con la pregunta a hacerse en vez de la regla a obedecer. Escrito para releerse duran...
Comenzar lección - Paso 58Depende
Referencia — Los cuatro árboles de decisión
Cuatro preguntas, hechas en orden, deciden casi todo lo que cubre este curso. Están abajo, y después las corré...
Comenzar lección