Journal
Sections
Réglages de lecture
Aucune voix pour cette langue dans ce navigateur.
Plus de voix
Code et termes techniques en anglais
Désactivé : la voix de la page lit tout, sans pause entre deux voix.
Aucune voix pour cette langue dans ce navigateur.
Plus de voix
D’autres voix : Microsoft Edge propose des voix naturelles en ligne, et Windows (Paramètres › Heure et langue › Voix), macOS et Android en installent d’autres.
Avancement
Section intitulée « Avancement »- React 19.3.0, Vite 8.3.0, TypeScript 7.0.2, Vitest 5.0.0, Testing Library et oxlint épinglés dans le
package.jsonet le fichier de verrouillage propres au cours -
check.sh:create-vite, le serveur de développement, une mise à jour HMR,tsc,vite build, oxlint, chaque extrait d’erreur et chaque test, comparés avecexpected/ - CI sur trois OS : verte depuis le 2026-09-16 (voir plus bas)
- Leçon 1 : un projet Vite
- Leçon 2 : composants et JSX
- Leçon 3 : état et rendu
- Leçon 4 : événements et formulaires
- Leçon 5 : effets
React 19.3.0, Vite 8.3.0, TypeScript 7.0.2 et Vitest 5.0.0, figés dans le fichier de verrouillage du cours. Les dix premières lignes concernent la chaîne d’outils ; les deux dernières, GuitarAlchemist/ga à 8cc8c5a, et, comme le dit l’entrée datée, rien n’y a été signalé à GA.
Il n’y a pas de tableau d’expériences : chaque entrée est une découverte écrite après coup. Les trois notes à vérifier de ce journal nomment ce qui n’a pas été mesuré ; aucune ne prédit ce que la mesure montrera.
| Attendu | Ce qui se passe | Où | Mesure | État |
|---|---|---|---|---|
| Vite retire les types TypeScript avec esbuild | Vite 8 assemble avec Rolldown et transforme avec Oxc ; @vitejs/plugin-react 6 ne dépend plus de Babel, et c’est Oxc qui fait aussi le Fast Refresh |
Vite 8.3.0, @vitejs/plugin-react 6.1.1 |
Lu dans les paquets installés | Par conception, chaîne d’outils changée. La phrase du cours TypeScript sur esbuild décrit GuitarAlchemist/ga, qui est en Vite 5, et reste vraie là-bas 2026-09-15 |
| Le serveur de développement affiche la même bannière que stdout soit un terminal ou non | Avec un stdout non-TTY, Vite omet press h + enter to show help, et un script qui attend cette ligne attend indéfiniment |
Vite 8.3.0, scripts/dev-start.mjs |
Le premier script n’a jamais vu la ligne et a laissé un serveur tourner sur le port 5199 | Reproduit ; le script attend désormais use --host to expose 2026-09-15 |
server.close() sur un serveur créé par l’API JS se résout après la dernière requête |
Sous Windows il ne se termine jamais : la première requête de module a lancé l’optimiseur de dépendances et l’a laissé tourner | Vite 8.3.0, Node.js 24.21.0, Windows, scripts/dev-module.mjs |
Detected unsettled top-level await, et le processus sort avec le code 13 |
Reproduit, non signalé ; waitForRequestsIdle() avant close() règle le problème. Linux et macOS non vérifiés, tracker de Vite non fouillé 2026-09-15 |
--base /learn/react-vite/ arrive à Vite tel qu’écrit |
Git Bash réécrit en chemin Windows tout argument qui commence par / |
Git Bash (MSYS) sous Windows, check.sh |
Les pages construites demandaient /Program Files/Git/learn/react-vite/assets/… |
Par conception dans MSYS ; MSYS_NO_PATHCONV=1 et des chemins de modules sans barre initiale le règlent 2026-09-15 |
| Testing Library démonte ce qu’un test a rendu, après chaque test | Seulement si le framework de test expose un afterEach global ; Vitest ne le fait pas sans globals: true |
@testing-library/react 16.3.3, Vitest 5.0.0 |
Le DOM d’un test restait dans le suivant, et les requêtes trouvaient deux formulaires | Par conception, et documenté ; setup.ts appelle cleanup dans afterEach 2026-09-15 |
| Un rapporteur de tests attribue la sortie console au test qui l’a produite | Le rapporteur par défaut de Vitest groupe la sortie console par moment, pas par test, et le groupement a changé d’une exécution à l’autre | Vitest 5.0.0 | Deux exécutions du même fichier ont groupé les mêmes journaux différemment | Reproduit ; un petit rapporteur maison range chaque journal avec son test, et check.sh lance un fichier par exécution de Vitest 2026-09-15 |
| Vitest isole les tests, donc l’état au niveau module repart de zéro entre eux | Il isole les fichiers de test ; un compteur au niveau module a continué de compter d’un test à l’autre | Vitest 5.0.0, premier test StrictMode de la leçon 3 | Le compteur a été conservé | Par conception ; le test passe maintenant le tableau modifié en prop 2026-09-15 |
FormEvent et FormEventHandler sont les types des gestionnaires de formulaires React |
@types/react 19.3.0 marque les deux @deprecated et renvoie vers ChangeEvent, InputEvent et SubmitEvent |
@types/react 19.3.0 |
Le commentaire de dépréciation dit « FormEvent doesn’t actually exist » ; ChangeEvent prend désormais deux paramètres de type |
Par conception ; la leçon 4 utilise SubmitEvent<HTMLFormElement> 2026-09-15 |
Le type de retour d’un composant est ReactNode |
Les types 19.3 acceptent les composants asynchrones, pour les Server Components | TypeScript 7.0.2, @types/react 19.3.0 |
tsc affiche Promise<ReactNode> | ReactNode dans son message |
Par conception 2026-09-15 |
| Le double rendu de StrictMode au montage est invisible dans le DOM | Un composant impur est rendu deux fois et le DOM garde la sortie du second rendu | React 19.3.0, StrictMode | Played so far: G G |
Par conception, et c’est ce dont la leçon 3 se sert pour rendre une impureté visible 2026-09-15 |
| Un jeton qui peut pousser du code peut pousser un fichier de workflow | GitHub exige en plus le scope workflow pour créer un fichier sous .github/workflows |
GitHub, le push de react-vite-examples.yml |
Le premier push a été refusé | Contourné en poussant le code sans le workflow. Le workflow est arrivé sur main plus tard : trois exécutions ont échoué le 2026-09-16, puis l’exécution 35098302366, à cd98475, est passée sous Ubuntu, Windows et macOS 2026-09-15 |
| Une ligne dépliée reste dépliée quand la liste est filtrée ou rafraîchie | DynamicPanel mémorise les lignes dépliées par leur position dans les données filtrées et rafraîchies : tout réordonnancement déplie une autre ligne |
GuitarAlchemist/ga à 8cc8c5a, DynamicPanel.tsx, lignes 76-120 |
Reproduit dans l’ExpandableList.tsx du cours ; les lignes du panneau sont des unknown[], sans champ d’identité connu |
Corrigé en amont par #733, fusionnée le 2026-09-24 : les lignes sont retenues par leur identité (id, sinon key, sinon le champ titre) 2026-09-15, 2026-09-24 |
| Un enfant qui remonte sa valeur au parent depuis un effet se stabilise après un tour | NotesSelector appelle onNotesChange depuis un effet qui en dépend, et ScaleSelector passe à chaque rendu un nouveau gestionnaire qui stocke un nouveau tableau |
GuitarAlchemist/ga à 8cc8c5a, NotesSelector.tsx 15-18 et ScaleSelector.tsx 18-21 |
La réduction du cours, en leçon 4, finit en Maximum update depth exceeded. Latent dans GA : aucune application ne rend ScaleSelector à ce commit |
Reproduit sur le ScaleSelector de GA lui-même par le test de #733, et corrigé par elle 2026-09-15, 2026-09-24 |
2026-09-15 — Versions
Section intitulée « 2026-09-15 — Versions »npm viewdonne React et React DOM 19.3.0, publiés le 9 septembre 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 etcreate-vite9.2.1. Le cours les épingle exactement danscode/react-vite/package.json, et utilise le Node.js 24.21.0 et le TypeScript 7.0.2 des autres cours du site.- Le modèle
react-tsdecreate-vite9.2.1 demande TypeScript~6.0.2, pas 7.0 : une plage avec~n’autorise que 6.0.x. Le cours utilise 7.0.2, ettsc -bvérifie les deux projets du modèle sans changement. Sonstrictest absent, parce que c’est le défaut depuis TypeScript 6.0, et son outil de lint est oxlint plutôt qu’ESLint, avec une option--eslintpour retrouver ESLint. - Vite 8 regroupe avec Rolldown et transforme avec Oxc. La leçon 1 du cours TypeScript dit que Vite retire les types avec esbuild : c’est vrai du Vite 5 de GA, et ne l’est plus de Vite 8.
@vitejs/plugin-react6 n’a pas non plus de dépendance à Babel ; Fast Refresh est fait par Oxc. - Le fichier de verrouillage écrit sous Windows liste les paquets natifs de toutes les plateformes comme dépendances optionnelles :
@rolldown/binding-*,@oxlint/*et@typescript/typescript-*.
2026-09-15 — Capturer le serveur de développement
Section intitulée « 2026-09-15 — Capturer le serveur de développement »- Le serveur de développement, les modules qu’il sert et le message HMR sont capturés par des scripts, pas à la main :
dev-start.mjsdémarreviteet l’arrête quand l’URL est affichée,dev-module.mjsdemande une URL par l’API JavaScript de Vite, ethmr.mjsse connecte au WebSocket HMR, modifie une copie d’App.tsxet affiche les messages. - Quand la sortie n’est pas un terminal, Vite n’affiche pas de ligne
press h + enter to show help. Mon premierdev-start.mjsattendait cette ligne, ne l’a jamais vue, et a laissé un serveur tourner sur le port 5199 ; il attend maintenantuse --host to expose. - Sous Windows,
server.close()appelé juste après la première requête de module ne se résolvait jamais : Node.js affichait « Detected unsettled top-level await » et quittait avec le code 13. La requête avait lancé l’optimiseur de dépendances, qui tournait encore. Attendreserver.environments.client.waitForRequestsIdle()avantclose()a réglé le problème. Je n’ai pas vérifié si Linux ou macOS se comportent de la même façon (à vérifier), ni cherché une issue Vite existante. - Git Bash sous Windows réécrit les arguments qui commencent par
/:vite build --base /learn/react-vite/a construit des pages qui demandaient/Program Files/Git/learn/react-vite/assets/….check.shdéfinitMSYS_NO_PATHCONV=1, et les scripts prennent les chemins de modules sans leur barre oblique initiale. - Les sorties sont normalisées par
normalize.mjs: les durées, le hash?v=des dépendances pré-empaquetées, les horodatages HMR et les source maps en ligne. Les noms des fichiers de production, commeindex-BQ_Vbf-Q.js, sont des hashs du contenu et sont gardés tels quels. - Le fait que Fast Refresh garde l’état n’est pas dans
check.sh, qui ne voit que le message WebSocket. Je l’ai vérifié à la main dans un navigateur : trois clics sur le compteur, deux sur le capo, puis une modification du titre dansApp.tsx. Le titre a changé, le compteur et le capo ont gardé leurs valeurs, et une variable définie surwindowavant la modification a survécu, donc la page n’avait pas été rechargée. Pour la leçon 1, j’ai aussi servi le build avec une erreur de type viavite previewet cliqué deux fois sur son bouton :Count is 01, puisCount is 011.
2026-09-15 — Vitest et Testing Library
Section intitulée « 2026-09-15 — Vitest et Testing Library »- React Testing Library démonte les composants rendus après chaque test seulement quand le framework de test expose un
afterEachglobal. Vitest ne le fait pas, sauf siglobals: trueest défini, donc le DOM d’un test restait dans le suivant et les requêtes trouvaient deux formulaires.src/testing/setup.tsappellecleanupdansafterEach, comme le décrit la documentation de Testing Library. - Le reporter par défaut de Vitest affiche la sortie console groupée par moment, pas par test, et le groupement changeait d’une exécution à l’autre. Le
reporter.mjsdu cours collecte chaque log avec son test et les affiche dans l’ordre à la fin, etcheck.shexécute un fichier de test par exécution de Vitest. - Les avertissements de développement de React, la clé manquante ou le champ contrôlé, vont dans
console.error, et le reporter les affiche avec un préfixeconsole.error:, donc les leçons les citent depuis les tests. - Un compteur au niveau du module, dans une première version du test StrictMode de la leçon 3, continuait de compter d’un test au suivant : Vitest isole les fichiers de test, pas les tests. Le composant impur reçoit maintenant en prop le tableau qu’il modifie.
tsconfig.app.jsonavait d’abord la libDOM.Iterable, pour décomposer uneNodeListdans un test. Avec TypeScript 7.0.2,DOMseul l’accepte ; la configuration du cours a maintenant le["ES2023", "DOM"]du modèle.
2026-09-15 — @types/react et React 19.3
Section intitulée « 2026-09-15 — @types/react et React 19.3 »@types/react19.3.0 marqueFormEventetFormEventHandlercomme@deprecated, avec le commentaire « FormEvent doesn’t actually exist », et renvoie versChangeEvent,InputEventetSubmitEvent.ChangeEventa deux paramètres de type, la cible courante et la cible. La leçon 4 utiliseSubmitEvent<HTMLFormElement>pouronSubmit.- Le type de retour d’un composant, dans le message de
tsc, estPromise<ReactNode> | ReactNode: les types acceptent les composants asynchrones, pour les Server Components. - En StrictMode, React 19.3 rend deux fois un composant impur au montage, et le DOM affiche la sortie du second rendu, « Played so far: G G ».
2026-09-15 — La CI
Section intitulée « 2026-09-15 — La CI »react-vite-examples.ymlexécutenpm cietbash check.shsur Ubuntu, Windows et macOS avec Node.js 24.21.0.check.shprend environ 50 secondes sur ma machine Windows.- Le premier push a été refusé : le jeton GitHub utilisé pour pousser n’a pas le scope
workflow, que GitHub exige pour créer un fichier sous.github/workflows. Le code a été poussé sans le workflow, et l’exécution sur trois OS reste à faire (à vérifier : les différences entre OS, comme l’ordre de la liste de fichiers decreate-viteou le format de sortie d’oxlint). - Mise à jour du 2026-09-22 : le workflow est arrivé sur
mainensuite. Trois exécutions ont échoué le 2026-09-16, puis l’exécution 35098302366, àcd98475(« lint with oxlint –format agent »), est passée sous Ubuntu, Windows et macOS. La nature des trois échecs n’est pas consignée ici.
2026-09-15 — Ce que le cours a trouvé dans GuitarAlchemist/ga
Section intitulée « 2026-09-15 — Ce que le cours a trouvé dans GuitarAlchemist/ga »Au commit 8cc8c5a, dans ReactComponents/ga-react-components et Apps/ga-client ; Apps/ga-dashboard est une application Angular 21, hors de ce cours. Rien de ceci n’a été signalé à GA.
- Des lignes dépliées retenues par index.
DynamicPanel.tsxgarde ses lignes dépliées dans unSet<number>de positions dans les données filtrées et interrogées périodiquement. Après un filtre ou une interrogation qui change l’ordre, c’est une autre ligne qui est dépliée. La leçon 3 le reproduit dansExpandableList.tsx. Les données du panneau sontunknown[]; le champ qui pourrait servir d’identité dépend des définitions de panneaux (à vérifier). - Une boucle de rendus entre deux composants.
NotesSelector.tsxappelleonNotesChangedepuis un effet qui en dépend, etScaleSelector.tsxpasse un nouveau gestionnaire à chaque rendu, qui stocke un nouveau tableau. La réduction de la leçon 4 se termine par « Maximum update depth exceeded ».ScaleSelectorstocke aussi dans l’étatscale, dérivé des notes. Il est exporté depuiscomponents/index.ts, et aucune application de GA ne le rend à ce commit, donc la boucle est latente. Je n’ai pas monté le composant de GA lui-même (à vérifier). - Une fenêtre glissante avec l’index pour clé.
DemerzelCriticOverlay.tsxdessine les dix derniers scores aveckey={i}, et ses barres onttransition: height 0.3s ease: une fois la fenêtre pleine, chaque nouveau score modifie et anime toutes les barres. L’exercice 3 de la leçon 2 montre la réutilisation des éléments ; je n’ai pas regardé l’animation (à vérifier). - Les règles React d’oxlint. oxlint 1.83.0 avec
react/no-array-index-key,react/exhaustive-depsettypescript/no-explicit-anysignale, dansga-react-components/src, 85 clés par index, 34 listes de dépendances d’effet ou de callback qui ne correspondent pas à ce que lit la fonction, et 11anyexplicites ; dansga-client/src, 6 clés par index.react/jsx-keyetreact/rules-of-hooksne signalent rien. Les chiffres sont des résultats de lint, pas des bugs : la plupart des clés par index sont sur des listes qui ne changent jamais. - Des effets sans nettoyage. Une recherche sommaire des appels
useEffectqui démarrent un timer, un écouteur ou un abonnement et ne renvoient pas de nettoyage en a trouvé un :ChatWidget.tsxdémarre unsetTimeoutde 300 ms qui n’est pas annulé si le composant est démonté avant. La recherche est textuelle, pas un parseur (à vérifier avant d’en tirer des conclusions). - Les options de scène.
SceneOptions.tsxprévient aussi son parent depuis un effet, une fois au montage, avec la règle des dépendances désactivée. Sa fusion des paramètres d’URL et des options sauvegardées fait déjà l’objet de la pull request ouverte GuitarAlchemist/ga#683, issue du cours JavaScript ; ce cours ne la corrige pas une seconde fois. - Build et serveur de développement. Le script
builddega-react-componentsestvite buildsanstsc, et sonvite.config.ts, 3 005 lignes, ajoute des middlewares pour des dizaines d’endpoints/dev-data/derrière un tunnel Cloudflare (leçon 1). Le scriptdevd’Apps/ga-clientrefuse de démarrer, et dit d’utiliserga-react-componentsà la place. Le dépôt suit aussi des fichiers générés :tsconfig.app.tsbuildinfo,playwright-reportettest-resultsdansga-react-components.
2026-09-24 — Correctifs amont
Section intitulée « 2026-09-24 — Correctifs amont »- #733, fusionnée le 2026-09-24, corrige les deux constats, chacun avec un test qui échoue sur l’ancien code.
DynamicPanelretient une ligne dépliée par son identité : l’idde la ligne, sinon sakey, sinon son champ titre, avec un suffixe pour les doublons ; seule une ligne qui n’a rien de tout cela retombe sur sa position.DynamicPanel.test.tsxdéplie Beta, puis filtre avec les puces ou envoie un sondage avec les lignes inversées. Sur l’ancien code, les deux tests échouent : c’est le détail d’Alpha qui s’affiche au lieu de celui de Beta.- La boucle de rendu est reproduite sur le composant de GA lui-même, pas seulement sur la réduction du cours. Le test monte le vrai
ScaleSelector, ses deux composants de diagramme remplacés par des simulacres, et fait lever une exception au gestionnaire du parent après 20 appels. Sur l’ancien code, il lève au montage, puis de nouveau après la saisie de « C E G » ; sans cette limite, le test restait bloqué plus de 120 s. Les deux composants remontent maintenant leur valeur depuis un effet qui ne dépend que des notes, et gardent le dernier gestionnaire dans une ref. Avec le correctif, le montage fait au plus 2 appels et la saisie exactement 1, avec['C','E','G']. - La boucle ne s’est jamais vue dans l’application : aucune page n’affiche ce
ScaleSelector, et ga-client a le sien.
À vérifier
Section intitulée « À vérifier »- Le blocage de
server.close()sous Linux et macOS, et l’existence d’une issue Vite à ce sujet. - Les
ScaleSelectoretNotesSelectorde GA montés avec Material UI, et l’animation de DemerzelCriticOverlay. - Un champ d’identité pour les lignes de
DynamicPaneldans les définitions de panneaux de GA.