Enable app-wide StrictMode and restore React effect checks
Some checks failed
Deploy Sokko G / deploy (push) Failing after 2s

This commit is contained in:
Shinuwa 2026-09-12 12:53:08 +02:00
parent b0e340efc7
commit a9b68a5712
5 changed files with 21 additions and 3 deletions

View file

@ -36,3 +36,4 @@
{"id":"int-9cb5a663c6e65593625066b25976439c","kind":"field_change","created_at":"2026-09-11T19:15:51.529868089Z","actor":"Shinuwa","issue_id":"sokko-g-5i3","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Library category now derives from anchor navigation; same-page hash/history navigation works; malformed anchors handled and obsolete RAF/scroll timers cleaned up. Existing library coverage and two new behavioral E2E pass. npm run check:full passes with 32 E2E; targeted set-state-in-effect lint passes."}} {"id":"int-9cb5a663c6e65593625066b25976439c","kind":"field_change","created_at":"2026-09-11T19:15:51.529868089Z","actor":"Shinuwa","issue_id":"sokko-g-5i3","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Library category now derives from anchor navigation; same-page hash/history navigation works; malformed anchors handled and obsolete RAF/scroll timers cleaned up. Existing library coverage and two new behavioral E2E pass. npm run check:full passes with 32 E2E; targeted set-state-in-effect lint passes."}}
{"id":"int-4ece504edad6e21c4829485c33215835","kind":"field_change","created_at":"2026-09-12T07:06:41.579702638Z","actor":"Shinuwa","issue_id":"sokko-g-739","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Tutorial visibility now follows toolbox identity and request transitions before commit; tour keyed by toolbox resets step and start latch. Two StrictMode behavioral tests cover identity changes, one-time flag consumption, dismissal and pending requests. check:full passes with 34 E2E; targeted set-state-in-effect lint passes."}} {"id":"int-4ece504edad6e21c4829485c33215835","kind":"field_change","created_at":"2026-09-12T07:06:41.579702638Z","actor":"Shinuwa","issue_id":"sokko-g-739","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Tutorial visibility now follows toolbox identity and request transitions before commit; tour keyed by toolbox resets step and start latch. Two StrictMode behavioral tests cover identity changes, one-time flag consumption, dismissal and pending requests. check:full passes with 34 E2E; targeted set-state-in-effect lint passes."}}
{"id":"int-c7fa4c94461f676392625658508ae231","kind":"field_change","created_at":"2026-09-12T10:15:48.480122568Z","actor":"Shinuwa","issue_id":"sokko-g-5rq","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Notepad now separates page identity from focused editing, replaces the editor DOM on page/module changes, preserves selection during local echoes and applies external updates after blur without stealing focus. Removed obsolete selection helpers and timestamp-only echo detection. check:full passes with 36 E2E; global set-state-in-effect diagnostic passes."}} {"id":"int-c7fa4c94461f676392625658508ae231","kind":"field_change","created_at":"2026-09-12T10:15:48.480122568Z","actor":"Shinuwa","issue_id":"sokko-g-5rq","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Notepad now separates page identity from focused editing, replaces the editor DOM on page/module changes, preserves selection during local echoes and applies external updates after blur without stealing focus. Removed obsolete selection helpers and timestamp-only echo detection. check:full passes with 36 E2E; global set-state-in-effect diagnostic passes."}}
{"id":"int-e79db6c1131fb3c5c57dde09917ef735","kind":"field_change","created_at":"2026-09-12T10:50:44.387707762Z","actor":"Shinuwa","issue_id":"sokko-g-8po","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Enabled app-wide StrictMode, restored recommended react-hooks/set-state-in-effect rule, documented development checks and added an effective ESLint configuration regression test. npm run check:full passed: lint, 101 Node tests, build and 36 E2E. All C10 subsets complete."}}

View file

@ -68,6 +68,12 @@ chargement initial des outils par Vite. Le parallélisme reste ajustable avec
`npm run test:e2e -- --workers=4`. Les traces des tests en échec sont conservées `npm run test:e2e -- --workers=4`. Les traces des tests en échec sont conservées
dans `test-results` et consultables depuis le rapport Playwright. dans `test-results` et consultables depuis le rapport Playwright.
L'application est enveloppée dans `StrictMode` : en développement (y compris les
E2E sur Vite), React rejoue certains rendus et cycles d'effets pour détecter les
effets de bord et les nettoyages manquants. Ces contrôles supplémentaires ne
s'exécutent pas en production. Les règles recommandées React Hooks, dont
`react-hooks/set-state-in-effect`, sont actives dans ESLint.
## Contenu éditable ## Contenu éditable
Les contenus maintenus à la main sont regroupés dans `website/public/data`. Les contenus maintenus à la main sont regroupés dans `website/public/data`.

View file

@ -34,7 +34,6 @@ export default [
}, },
rules: { rules: {
...reactHooks.configs.recommended.rules, ...reactHooks.configs.recommended.rules,
"react-hooks/set-state-in-effect": "off",
"no-unused-vars": ["error", { "no-unused-vars": ["error", {
argsIgnorePattern: "^_", argsIgnorePattern: "^_",
varsIgnorePattern: "^_", varsIgnorePattern: "^_",

12
tests/react-lint.test.mjs Normal file
View file

@ -0,0 +1,12 @@
// Rôle : vérifie que les contrôles React critiques restent actifs dans la configuration ESLint effective.
import { test } from "node:test";
import assert from "node:assert/strict";
import { ESLint } from "eslint";
test("React effect and purity checks are enabled for application sources", async () => {
const eslint = new ESLint();
const config = await eslint.calculateConfigForFile("website/src/main.jsx");
for (const rule of ["react-hooks/set-state-in-effect", "react-hooks/purity", "react-hooks/rules-of-hooks", "react-hooks/exhaustive-deps"]) {
assert.ok(config.rules[rule][0] > 0, `${rule} must remain enabled`);
}
});

View file

@ -1,6 +1,6 @@
// Rôle : point d'entrée React, assemble données, routes, shell et overlays. // Rôle : point d'entrée React, assemble données, routes, shell et overlays.
/* eslint-disable react-refresh/only-export-components -- point d'entrée Vite sans export de composant. */ /* eslint-disable react-refresh/only-export-components -- point d'entrée Vite sans export de composant. */
import { lazy, Suspense, useCallback, useEffect, useState } from "react"; import { lazy, StrictMode, Suspense, useCallback, useEffect, useState } from "react";
import { createRoot } from "react-dom/client"; import { createRoot } from "react-dom/client";
import "./styles/main.scss"; import "./styles/main.scss";
import { AppOverlays } from "./components/AppOverlays.jsx"; import { AppOverlays } from "./components/AppOverlays.jsx";
@ -175,4 +175,4 @@ function App() {
); );
} }
createRoot(document.querySelector("#app")).render(<App />); createRoot(document.querySelector("#app")).render(<StrictMode><App /></StrictMode>);