# Frontend — Risques & vigilance : Navigation > Extrait de la base de connaissance Lead_tech. Voir `knowledge/frontend/risques/README.md` pour l'index complet. --- ## Écran détail Expo Router — store vide en deep link / reload ### Risques - L'écran détail (`[slug].tsx`) lit ses données depuis un store Zustand peuplé par l'écran liste - En deep link, kill + reopen ou navigation OS back, le store est vide → "introuvable" affiché à tort ### Symptômes - Écran détail vide ou erreur "non trouvé" sur accès direct (pas via la liste) - Fonctionne normalement en navigation standard mais échoue sur reload ### Bonnes pratiques / mitigations ```typescript // useEffect de secours dans l'écran détail useEffect(() => { if (!accessToken) return; if (items.length > 0 || isLoading || errorState) return; void fetchItems(accessToken); }, [accessToken, items.length, isLoading, errorState, fetchItems]); ``` - Ne pas afficher "introuvable" avant d'avoir vérifié que le store a bien été peuplé - Contexte technique : Expo Router / Zustand — app-alexandrie story 4.1, 20-03-2026 --- ## `useEffect` fetch — guard incomplet sur les états terminaux ### Risques - Si l'état "zéro résultat intentionnel" (ex : `paywallRequired`) n'est pas dans les conditions de court-circuit, le fetch est re-déclenché à chaque re-render ou focus - Boucle de fetch infini sur un état métier normal ### Symptômes - `forums.length === 0` et `isLoading === false` → le guard ne court-circuite pas → fetch re-déclenché en boucle - Visible en focus sur l'écran depuis un autre onglet ### Bonnes pratiques / mitigations ```typescript // ❌ Pattern à risque — re-fetch si paywallRequired (forums vide + isLoading false) if (forums.length > 0 || isLoading) return; // ✅ Pattern correct — court-circuit sur l'état terminal if (forums.length > 0 || isLoading || paywallRequired) return; ``` **Règle** : les états "zéro résultat intentionnel" (liste vide + flag métier) doivent être traités comme "données présentes" dans le guard de fetch. - Contexte technique : React Native / Zustand / Expo Router — app-alexandrie story 4.1, 20-03-2026 --- ## Store Zustand : collections sans clé de contexte (navigation inter-contexte) ### Risques - Un store qui stocke des collections dépendant d'un paramètre de navigation (forumSlug, threadId...) sans stocker ce paramètre affiche des données périmées lors d'une navigation inter-contexte ### Symptômes - Naviguer du forum A vers le forum B affiche encore les catégories/threads du forum A - Guard `if (items.length > 0) return` empêche le rechargement lors d'un changement de contexte ### Bonnes pratiques / mitigations - Stocker la clé de contexte avec les données : `categoriesForumSlug: string | null` - Invalider si `categoriesForumSlug !== currentForumSlug` avant de retourner depuis le cache - Ou supprimer le guard et dépendre uniquement du changement de paramètre dans le `useEffect` - Contexte technique : React Native / Zustand / Expo Router — app-alexandrie 23-03-2026 --- ## Expo Router — mapping `name`/`label` des tabs inversés sans erreur ### Risques - `` route vers `app/(tabs)/x.tsx` — le `title` (label affiché) est totalement indépendant du routage - Un label "Communauté" sur `name="explore"` affiche `explore.tsx` sans aucune erreur de build ni de lint ### Symptômes - Le bon label est affiché, mais l'écran affiché est celui d'un boilerplate ou d'un autre module - Bug invisible jusqu'au test manuel de chaque onglet ### Bonnes pratiques / mitigations - Lors de tout ajout ou renommage de tab, valider visuellement que chaque label correspond à l'écran attendu - Convention : aligner le `name` et le nom de fichier avec le wording du label (ex : `name="community"` → `community.tsx` → `title="Communauté"`) - Ajouter un test de smoke de navigation si la structure de tabs est critique - Contexte technique : Expo Router — app-alexandrie, 25-03-2026 --- ## Expo Router — ne jamais préfixer le groupe dans `router.push` ### Risques - `router.push('/(auth)/forgot-password')` depuis un écran `(tabs)/` peut échouer silencieusement ou lever une erreur selon la version d'Expo Router - La résolution des groupes de routes se fait par contexte de navigation — un préfixe de groupe explicite n'est pas un chemin de route valide ### Symptômes - Navigation vers un écran `(auth)/` qui n'aboutit pas ou lève une erreur au runtime - Fonctionne dans certaines versions d'Expo Router mais pas d'autres ### Bonnes pratiques / mitigations ```typescript // ❌ Anti-pattern — préfixe de groupe explicite router.push('/(auth)/forgot-password'); // ✅ Pattern correct — chemin sans groupe router.push('/forgot-password' as never); ``` - Règle : les groupes `(auth)`, `(tabs)`, etc. sont des conventions d'organisation de fichiers, pas des segments de route — ne jamais les inclure dans les appels de navigation programmatique - Contexte technique : Expo Router — app-alexandrie, 25-03-2026