Diario
Secciones
Ajustes de lectura
Ninguna voz para este idioma en este navegador.
Más voces
Código y términos técnicos en inglés
Desactivado: la voz de la página lo lee todo, sin pausa entre dos voces.
Ninguna voz para este idioma en este navegador.
Más voces
Más voces: Microsoft Edge ofrece voces naturales en línea, y Windows (Configuración › Hora e idioma › Voz), macOS y Android instalan otras.
Progreso
Sección titulada «Progreso»- React 19.3.0, Vite 8.3.0, TypeScript 7.0.2, Vitest 5.0.0, Testing Library y oxlint fijados en el propio
package.jsondel curso y en su archivo de bloqueo -
check.sh:create-vite, el servidor de desarrollo, una actualización HMR,tsc,vite build, oxlint, cada fragmento de error y cada prueba, comparados conexpected/ - CI en tres sistemas operativos: en verde desde el 2026-09-16 (ver más abajo)
- Lección 1: un proyecto Vite
- Lección 2: componentes y JSX
- Lección 3: estado y renderizado
- Lección 4: eventos y formularios
- Lección 5: efectos
React 19.3.0, Vite 8.3.0, TypeScript 7.0.2 y Vitest 5.0.0, fijados en el archivo de bloqueo del curso. Las diez primeras filas son de la cadena de herramientas; las dos últimas, de GuitarAlchemist/ga en 8cc8c5a, y, como dice la entrada fechada, nada de eso se ha reportado a GA.
No hay tabla de experimentos: cada entrada es un descubrimiento escrito después. Las tres notas por verificar de este diario nombran lo que no se ha medido; ninguna predice lo que mostrará la medición.
| Esperado | Lo que pasa | Dónde | Medición | Estado |
|---|---|---|---|---|
| Vite quita los tipos de TypeScript con esbuild | Vite 8 empaqueta con Rolldown y transforma con Oxc; @vitejs/plugin-react 6 ya no depende de Babel, y el Fast Refresh también lo hace Oxc |
Vite 8.3.0, @vitejs/plugin-react 6.1.1 |
Leído en los paquetes instalados | Por diseño, cadena de herramientas cambiada. La frase del curso de TypeScript sobre esbuild describe GuitarAlchemist/ga, que está en Vite 5, y sigue siendo cierta allí 2026-09-15 |
| El servidor de desarrollo imprime el mismo aviso tanto si stdout es un terminal como si no | Con un stdout que no es TTY, Vite omite press h + enter to show help, y un script que espera esa línea espera para siempre |
Vite 8.3.0, scripts/dev-start.mjs |
El primer script nunca vio la línea y dejó un servidor corriendo en el puerto 5199 | Reproducido; el script espera ahora use --host to expose 2026-09-15 |
server.close() en un servidor creado con la API de JS se resuelve tras la última petición |
En Windows nunca termina: la primera petición de módulo arrancó el optimizador de dependencias y lo dejó en marcha | Vite 8.3.0, Node.js 24.21.0, Windows, scripts/dev-module.mjs |
Detected unsettled top-level await, y el proceso sale con el código 13 |
Reproducido, no reportado; waitForRequestsIdle() antes de close() lo resuelve. Linux y macOS sin comprobar, tracker de Vite sin buscar 2026-09-15 |
--base /learn/react-vite/ llega a Vite tal como se escribió |
Git Bash reescribe como ruta de Windows cualquier argumento que empiece por / |
Git Bash (MSYS) en Windows, check.sh |
Las páginas construidas pedían /Program Files/Git/learn/react-vite/assets/… |
Por diseño en MSYS; MSYS_NO_PATHCONV=1 y rutas de módulos sin barra inicial lo resuelven 2026-09-15 |
| Testing Library desmonta lo que un test renderizó, tras cada test | Solo si el framework de tests expone un afterEach global; Vitest no lo hace sin globals: true |
@testing-library/react 16.3.3, Vitest 5.0.0 |
El DOM de un test se quedaba en el siguiente, y las consultas encontraban dos formularios | Por diseño, y documentado; setup.ts llama a cleanup en afterEach 2026-09-15 |
| Un reporter de tests atribuye la salida de consola al test que la produjo | El reporter por defecto de Vitest agrupa la salida de consola por momento, no por test, y la agrupación cambió entre ejecuciones | Vitest 5.0.0 | Dos ejecuciones del mismo archivo agruparon los mismos logs de forma distinta | Reproducido; un pequeño reporter propio guarda cada log con su test, y check.sh lanza un archivo por ejecución de Vitest 2026-09-15 |
| Vitest aísla los tests, así que el estado a nivel de módulo se reinicia entre ellos | Aísla archivos de test; un contador a nivel de módulo siguió contando de un test al siguiente | Vitest 5.0.0, primer test de StrictMode de la lección 3 | El contador se conservó | Por diseño; el test pasa ahora el array modificado como prop 2026-09-15 |
FormEvent y FormEventHandler son los tipos de los manejadores de formularios de React |
@types/react 19.3.0 marca ambos como @deprecated y remite a ChangeEvent, InputEvent y SubmitEvent |
@types/react 19.3.0 |
El comentario de obsolescencia dice “FormEvent doesn’t actually exist”; ChangeEvent recibe ahora dos parámetros de tipo |
Por diseño; la lección 4 usa SubmitEvent<HTMLFormElement> 2026-09-15 |
El tipo de retorno de un componente es ReactNode |
Los tipos de la 19.3 aceptan componentes asíncronos, para los Server Components | TypeScript 7.0.2, @types/react 19.3.0 |
tsc imprime Promise<ReactNode> | ReactNode en su mensaje |
Por diseño 2026-09-15 |
| El doble renderizado de StrictMode al montar es invisible en el DOM | Un componente impuro se renderiza dos veces y el DOM conserva la salida del segundo renderizado | React 19.3.0, StrictMode | Played so far: G G |
Por diseño, y es lo que la lección 3 usa para hacer visible una impureza 2026-09-15 |
| Un token que puede subir código puede subir un archivo de workflow | GitHub exige además el scope workflow para crear un archivo bajo .github/workflows |
GitHub, el push de react-vite-examples.yml |
El primer push fue rechazado | Sorteado subiendo el código sin el workflow. El workflow llegó a main más tarde: tres ejecuciones fallaron el 2026-09-16, y luego la ejecución 35098302366, en cd98475, pasó en Ubuntu, Windows y macOS 2026-09-15 |
| Una fila desplegada sigue desplegada cuando la lista se filtra o se refresca | DynamicPanel guarda las filas desplegadas por su posición en los datos filtrados y refrescados: cualquier reordenación despliega otra fila |
GuitarAlchemist/ga en 8cc8c5a, DynamicPanel.tsx, líneas 76-120 |
Reproducido en el ExpandableList.tsx del curso; las filas del panel son unknown[], sin campo de identidad conocido |
Corregido upstream por #733, fusionada el 2026-09-24: las filas se recuerdan por su identidad (id, si no key, si no el campo de título) 2026-09-15, 2026-09-24 |
| Un hijo que informa de su valor al padre desde un efecto se estabiliza tras una vuelta | NotesSelector llama a onNotesChange desde un efecto que depende de él, y ScaleSelector pasa en cada renderizado un manejador nuevo que guarda un array nuevo |
GuitarAlchemist/ga en 8cc8c5a, NotesSelector.tsx 15-18 y ScaleSelector.tsx 18-21 |
La reducción del curso, en la lección 4, acaba en Maximum update depth exceeded. Latente en GA: ninguna aplicación renderiza ScaleSelector en ese commit |
Reproducido en el propio ScaleSelector de GA por la prueba de #733, y corregido por ella 2026-09-15, 2026-09-24 |
2026-09-15 — Versiones
Sección titulada «2026-09-15 — Versiones»npm viewda React y React DOM 19.3.0, publicados el 9 de septiembre de 2026, Vite 8.3.0,@vitejs/plugin-react6.1.1, Vitest 5.0.0, jsdom 30.0.1,@testing-library/react16.3.3,@testing-library/dom10.4.2,@testing-library/user-event14.6.7, oxlint 1.83.0 ycreate-vite9.2.1. El curso los fija exactamente encode/react-vite/package.json, y usa el Node.js 24.21.0 y el TypeScript 7.0.2 de los demás cursos del sitio.- La plantilla
react-tsdecreate-vite9.2.1 pide TypeScript~6.0.2, no 7.0: un rango con~solo admite 6.0.x. El curso usa 7.0.2, ytsc -bverifica los dos proyectos de la plantilla sin ningún cambio. Sustrictno aparece, porque es el valor por defecto desde TypeScript 6.0, y su herramienta de lint es oxlint en lugar de ESLint, con una opción--eslintpara recuperar ESLint. - Vite 8 empaqueta con Rolldown y transforma con Oxc. La lección 1 del curso de TypeScript dice que Vite elimina los tipos con esbuild: es cierto para el Vite 5 de GA, y ya no para Vite 8.
@vitejs/plugin-react6 tampoco depende de Babel; Fast Refresh lo hace Oxc. - El archivo de bloqueo escrito en Windows lista los paquetes nativos de todas las plataformas como dependencias opcionales:
@rolldown/binding-*,@oxlint/*y@typescript/typescript-*.
2026-09-15 — Capturar el servidor de desarrollo
Sección titulada «2026-09-15 — Capturar el servidor de desarrollo»- El servidor de desarrollo, los módulos que sirve y el mensaje HMR se capturan con scripts, no a mano:
dev-start.mjsiniciavitey lo detiene cuando se imprime la URL,dev-module.mjssolicita una URL mediante la API JavaScript de Vite, yhmr.mjsse conecta al WebSocket de HMR, edita una copia deApp.tsxe imprime los mensajes. - Cuando la salida no es un terminal, Vite no imprime la línea
press h + enter to show help. Mi primerdev-start.mjsesperaba esa línea, nunca la vio, y dejó un servidor en marcha en el puerto 5199; ahora esperause --host to expose. - En Windows,
server.close()llamado justo después de la primera solicitud de módulo nunca terminaba: Node.js imprimió “Detected unsettled top-level await” y salió con el código 13. La solicitud había arrancado el optimizador de dependencias, que seguía en marcha. Esperarserver.environments.client.waitForRequestsIdle()antes declose()lo arregló. No he comprobado si Linux o macOS se comportan igual (por verificar), ni he buscado una issue existente de Vite. - Git Bash en Windows reescribe los argumentos que empiezan por
/:vite build --base /learn/react-vite/generó páginas que pedían/Program Files/Git/learn/react-vite/assets/….check.shdefineMSYS_NO_PATHCONV=1, y los scripts reciben las rutas de módulo sin su barra inicial. - Las salidas se normalizan con
normalize.mjs: duraciones, el hash?v=de las dependencias preempaquetadas, las marcas de tiempo de HMR y los source maps en línea. Los nombres de los archivos de producción, comoindex-BQ_Vbf-Q.js, son hashes del contenido y se mantienen tal cual. - Que Fast Refresh conserve el estado no está en
check.sh, que solo ve el mensaje del WebSocket. Lo comprobé a mano en un navegador: tres clics en el contador, dos en el capo, y luego una edición del encabezado enApp.tsx. El encabezado cambió, el contador y el capo conservaron sus valores, y una variable definida enwindowantes de la edición sobrevivió, así que la página no se había recargado. Para la lección 1, también serví convite previewel build con un error de tipo e hice clic dos veces en su botón:Count is 01, y luegoCount is 011.
2026-09-15 — Vitest y Testing Library
Sección titulada «2026-09-15 — Vitest y Testing Library»- React Testing Library desmonta los componentes renderizados después de cada prueba solo cuando el framework de pruebas expone un
afterEachglobal. Vitest no lo hace, salvo conglobals: true, así que el DOM de una prueba se quedaba en la siguiente y las consultas encontraban dos formularios.src/testing/setup.tsllama acleanupenafterEach, como describe la documentación de Testing Library. - El reporter por defecto de Vitest imprime la salida de consola agrupada por momento, no por prueba, y la agrupación cambiaba entre ejecuciones. El
reporter.mjsdel curso recoge cada log con su prueba y los imprime en orden al final, ycheck.shejecuta un archivo de prueba por ejecución de Vitest. - Las advertencias de desarrollo de React, la clave que falta o el input controlado, van a
console.error, y el reporter las imprime con un prefijoconsole.error:, así que las lecciones las citan a partir de las pruebas. - Un contador a nivel de módulo, en una primera versión de la prueba de StrictMode de la lección 3, seguía contando de una prueba a la siguiente: Vitest aísla los archivos de prueba, no las pruebas. El componente impuro recibe ahora como prop el array que modifica.
tsconfig.app.jsontenía al principio la libDOM.Iterable, para expandir unNodeListen una prueba. Con TypeScript 7.0.2,DOMsolo lo acepta; la configuración del curso tiene ahora el["ES2023", "DOM"]de la plantilla.
2026-09-15 — @types/react y React 19.3
Sección titulada «2026-09-15 — @types/react y React 19.3»@types/react19.3.0 marcaFormEventyFormEventHandlercomo@deprecated, con el comentario “FormEvent doesn’t actually exist”, y remite aChangeEvent,InputEventySubmitEvent.ChangeEventtiene dos parámetros de tipo, el current target y el target. La lección 4 usaSubmitEvent<HTMLFormElement>paraonSubmit.- El tipo de retorno de un componente, en el mensaje de
tsc, esPromise<ReactNode> | ReactNode: los tipos aceptan componentes asíncronos, para los Server Components. - En StrictMode, React 19.3 renderiza dos veces un componente impuro al montarlo, y el DOM muestra la salida del segundo render, “Played so far: G G”.
2026-09-15 — La CI
Sección titulada «2026-09-15 — La CI»react-vite-examples.ymlejecutanpm ciybash check.shen Ubuntu, Windows y macOS con Node.js 24.21.0.check.shtarda unos 50 segundos en mi máquina Windows.- El primer push fue rechazado: el token de GitHub usado para el push no tiene el scope
workflow, que GitHub exige para crear un archivo bajo.github/workflows. El código se subió sin el workflow, y la ejecución en tres sistemas operativos sigue pendiente (por verificar: diferencias entre sistemas, como el orden de la lista de archivos decreate-viteo el formato de salida de oxlint). - Actualización del 2026-09-22: el workflow llegó a
maindespués. Tres ejecuciones fallaron el 2026-09-16, y luego la ejecución 35098302366, encd98475(«lint with oxlint –format agent»), pasó en Ubuntu, Windows y macOS. En qué consistieron los tres fallos no queda registrado aquí.
2026-09-15 — Lo que el curso encontró en GuitarAlchemist/ga
Sección titulada «2026-09-15 — Lo que el curso encontró en GuitarAlchemist/ga»En el commit 8cc8c5a, en ReactComponents/ga-react-components y Apps/ga-client; Apps/ga-dashboard es una aplicación Angular 21, fuera de este curso. Nada de esto se ha comunicado a GA.
- Filas expandidas recordadas por índice.
DynamicPanel.tsxguarda sus filas expandidas en unSet<number>de posiciones en los datos filtrados y consultados periódicamente. Tras un filtro o una consulta que cambia el orden, queda expandida otra fila. La lección 3 lo reproduce enExpandableList.tsx. Los datos del panel sonunknown[]; qué campo podría servir de identidad depende de las definiciones de los paneles (por verificar). - Un bucle de renders entre dos componentes.
NotesSelector.tsxllama aonNotesChangedesde un efecto que depende de él, yScaleSelector.tsxpasa un manejador nuevo en cada render, que guarda un array nuevo. La reducción de la lección 4 termina con “Maximum update depth exceeded”.ScaleSelectortambién guarda en el estadoscale, derivado de las notas. Se exporta desdecomponents/index.ts, y ninguna aplicación de GA lo renderiza en este commit, así que el bucle está latente. No he montado el propio componente de GA (por verificar). - Una ventana deslizante con clave por índice.
DemerzelCriticOverlay.tsxdibuja las diez últimas puntuaciones conkey={i}, y sus barras tienentransition: height 0.3s ease: una vez llena la ventana, cada nueva puntuación cambia y anima todas las barras. El ejercicio 3 de la lección 2 muestra la reutilización de elementos; no he observado la animación (por verificar). - Las reglas React de oxlint. oxlint 1.83.0 con
react/no-array-index-key,react/exhaustive-depsytypescript/no-explicit-anyseñala, enga-react-components/src, 85 claves por índice, 34 listas de dependencias de efectos o callbacks que no coinciden con lo que lee la función, y 11anyexplícitos; enga-client/src, 6 claves por índice.react/jsx-keyyreact/rules-of-hooksno señalan nada. Los recuentos son resultados de lint, no errores: la mayoría de las claves por índice están en listas que nunca cambian. - Efectos sin limpieza. Una búsqueda aproximada de las llamadas a
useEffectque inician un temporizador, un listener o una suscripción y no devuelven limpieza encontró una:ChatWidget.tsxinicia unsetTimeoutde 300 ms que no se cancela si el componente se desmonta antes. La búsqueda es textual, no un parser (por verificar antes de sacar conclusiones). - Opciones de escena.
SceneOptions.tsxtambién notifica a su padre desde un efecto, una vez al montarse, con la regla de dependencias desactivada. Su fusión de los parámetros de URL y las opciones guardadas ya es objeto de la pull request abierta GuitarAlchemist/ga#683, del curso de JavaScript; este curso no la corrige otra vez. - Build y servidor de desarrollo. El script
builddega-react-componentsesvite buildsintsc, y suvite.config.ts, de 3005 líneas, añade middleware para decenas de endpoints/dev-data/detrás de un túnel de Cloudflare (lección 1). El scriptdevdeApps/ga-clientse niega a arrancar, y dice que se usega-react-componentsen su lugar. El repositorio también versiona archivos generados:tsconfig.app.tsbuildinfo,playwright-reportytest-resultsenga-react-components.
2026-09-24 — Correcciones upstream
Sección titulada «2026-09-24 — Correcciones upstream»- #733, fusionada el 2026-09-24, corrige los dos hallazgos, cada uno con una prueba que falla con el código antiguo.
DynamicPanelrecuerda una fila desplegada por su identidad: elidde la fila, si no sukey, si no su campo de título, con un sufijo para las repeticiones; solo una fila sin nada de eso vuelve a su posición.DynamicPanel.test.tsxdespliega Beta y luego filtra con los chips o envía un sondeo con las filas invertidas. Con el código antiguo, las dos pruebas fallan: se muestra el detalle de Alpha en lugar del de Beta.- El bucle de renderizado se reproduce en el propio componente de GA, no solo en la reducción del curso. La prueba monta el
ScaleSelectorreal, con sus dos componentes de diagrama simulados, y hace que el manejador del padre lance una excepción tras 20 llamadas. Con el código antiguo lanza al montar y otra vez tras escribir «C E G»; sin ese límite, la prueba se quedaba colgada más de 120 s. Los dos componentes informan ahora desde un efecto que solo depende de las notas, y guardan el último manejador en una ref. Con la corrección, el montaje hace como mucho 2 llamadas y la escritura exactamente 1, con['C','E','G']. - El bucle nunca se vio en la aplicación: ninguna página muestra este
ScaleSelector, y ga-client tiene el suyo.
Por verificar
Sección titulada «Por verificar»- El bloqueo de
server.close()en Linux y macOS, y si Vite tiene una issue para ello. - El
ScaleSelectory elNotesSelectorde GA montados con Material UI, y la animación de DemerzelCriticOverlay. - Un campo de identidad para las filas de
DynamicPanelen las definiciones de paneles de GA.