- Expédié
- 26 août 2026 à 05:40 UTC
- Auteur
- kamo
- Commite
- 2241a5c
useUserInfo a tenu sa session en trois cellules d'utilisationState. Il dispose de 187 sites d'appel et environ 27 ils sont montés pour l'ensemble de la session - la nav, chaque fournisseur de shell, le rampe de lancement. Le DEMANDE était déjà coalescé, donc il n'y avait jamais qu'un seul appel /api/utilisateur-info, mais quand il ont résolu les 27 instances appelées leur propre setUserInfo avec les mêmes données. Vingt-sept des mises à jour de React indépendantes portant un état identique, sur chaque onglement ciblé et toutes les cinq minutes tiques. L'état passe dans un module stockant derrière useSyncExternalStore, donc un rafraîchissement est une écriture et un passage par lots de rendus. Le magasin est app/lib/userInfoStore.ts plutôt qu'un module crochet-local pour une raison spécifique: Rien dans ce projet ne peut détecter une régression des droits. Il n'y a pas de "libraire d'essai, pas de test" met en place un composant, et app/hooks/- n'est pas dans la liste d'inclusion de vitest - un test placé à côté de la liste crochet passerait en ne s'exécutant jamais. app/lib/- est inclus, donc les règles qui transfèrent les droits à travers le produit a maintenant 25 tests couvrant chaque chemin d'écriture. Trois propriétés sont porteuses et chacune est épinglée par un essai: Le chargement commence VRAI et est une serrure à sens unique. Les gardiens des droits tombent à un DENY, pas à a wait, et checkRight s'ouvre avec "si (utilisateurInfo) retourne faux" - donc un rapport de magasin chargement: faux avant que les données n'arrivent, ne donne "aucune autorisation" à un membre qui détient le droit, et tire le vingt « useEffect(..., [chargement) et refoule les droits sur le premier rendu non-charge. Rien ne s'écrase et aucun test ne passe. De même, il ne doit jamais revenir à la vérité. ou chaque garde de l'application clignote son état de chargement toutes les cinq minutes. Les écrits ne sont que par construction. Sur le serveur, un processus serve chaque concurrent demande, donc une variable de module conservant les droits d'un membre est un partage avec tous les autres render() de mot. constant congelé au lieu de lire l'inscactile mutable. Cette constante est également obligatoire: un shell authentifié est rendu par le serveur et ce crochet est atteint pendant le passage du serveur à partir du Arbre client de la disposition des racines, où React 19 jette plutôt que de retomber, sans limite Au-dessus d'AuthedChrome pour l'attraper. L'instantané est tenu, jamais reconstruit. loadUserInfoShared retourne un objet fraîchement analysé tous temps, c'est précisément la raison pour laquelle les 27 instances ont été redonnées; un getSnapshot qui en a construit un serait Non seulement les renouer, mais les lancer. Les charges utiles équivalentes ne publient plus du tout, de sorte que les consommateurs la mise à l'écoute des mémos d'utilisateurInfo identité et SettingsAppPinsContext's nav gate above all Recalculer toutes les cinq minutes pour une charge utile qui n'a pas changé. Trois décisions dignes d'être présentées, parce que chacune avait une alternative défendable: La navigation /logout est maintenant fermée sur le fait qu'il y a un abonné. Le vieux isMountedRef garde assis au-dessus de l'interrupteur, pas sur un setState, donc il a sauté la redirection - une instance qui n'a pas monté le milieu de vol n'a pas navigué. Supprimer la refright, qui est le mouvement habituel lors de l'adoption d'un Un module de stockage aurait silencieusement promu ce qui est redirigé de conditionnel à condition. Seule la première charge est avant-plan; plus tard, se rafraîchit en arrière-plan. Les droits restent frais sur la navigation comme avant, mais une erreur transitoire sur un monte tardif ne peut plus blanc les 27 consommateurs, lorsqu'auparavant, le seul cas qui l'a frappé. Les sept appelants externes loadUserInfoShared ne publient délibérément pas. Ils tirent sur websocket se reconnecte à des moments arbitraires, et conduite du portage du produit à partir d'une surface de déclenchement Personne ne regarde que la virilité bornée de ne pas le faire - ils lisent scalar une identité qui ne peut pas changer à l'intérieur d'une session. Les projecteurs sont laissés intentionnellement sous forme de flèches simples. Leur stabilisation est l'instinct naturel ici et installerait silencieusement neuf sites d'appels - useHrOverview, useSubscriptionPermissions, PlateformeRightsContext et six autres - qui dépendent de l'instabilité de l'identité d'aujourd'hui pour rester frais, calculer une fois contre un instantané nul à la place. L'entrée /Goingout allowlist dans check-client-navigation.mjs suit la ligne pour laquelle elle existe. Vérifié: tsc clean, les 10 gardes passent, 3286 tests verts, les compilations de construction de production, et la un serveur autonome rend toujours le shell authentifié 200, 16,238 octets de DOM sur 153 éléments, deux en-têtes, dix boutons, My Businesses / My Profile / Log out. Étend un être humain à Cliquez à travers le nav-lié de droits, un membre des droits limités, et une session d'expiration avant lui navires.