Refactoring React Native : de 800 lignes a 100 lignes
Il y a un moment où tu ouvres un fichier et tu sens physiquement le poids de la dette technique. Mon écran principal faisait 800 lignes. Un seul fichier. Logique métier, rendu UI, gestion d'état, appels API — tout mélangé dans un composant monolithique impossible à maintenir. Et ce n'était pas un cas isolé : j'avais 16 écrans dans le même état.
Ce que je vais te raconter ici, c'est comment j'ai transformé un codebase chaotique en une architecture propre. Pas en une révolution spectaculaire, mais en un refactoring méthodique, écran par écran, erreur par erreur.
Points clés à retenir :
- Un hook custom par écran sépare la logique métier du rendu UI
- Le pattern "orchestrateur + sous-composants" réduit les fichiers de 800 à 100 lignes
- ESLint avec règles strictes (zéroany, promesses awaited) élimine des bugs silencieux
- La dette technique est un coût réel mesurable en temps, bugs et motivation
- Refactorer écran par écran permet de livrer en continu sans casser l'existant
Pourquoi un composant de 800 lignes est-il un problème ?
La réponse évidente : c'est illisible. Mais le vrai problème est plus insidieux. Un composant monolithique :
- Cache les bugs : quand tout est dans le même fichier, les effets de bord sont imprévisibles. Modifier la logique de filtre peut casser l'animation de transition sans que tu comprennes pourquoi.
- Ralentit le développement : chaque modification nécessite de comprendre l'ensemble du fichier. Tu passes 20 minutes à "lire" avant de pouvoir écrire 5 lignes.
- Rend le debug impossible : quand un bug survient, tu as 800 lignes de suspects. Pas de frontière claire entre les responsabilités.
- Détériore la motivation : ouvrir un fichier monstrueux chaque matin, ça pèse. C'est le genre de friction invisible qui ralentit un projet indie.
"Tu es seul, qui va lire ce code ?" Moi. Moi dans trois mois quand j'aurai oublié pourquoi cet écran fait ce qu'il fait. La dette technique n'est pas une métaphore. C'est un coût réel qui se paie en temps, en bugs, et en motivation.
Quelle stratégie de découpage adopter ?
J'ai refactoré les 16 écrans en suivant une structure consistante. Le pattern est simple mais puissant :
1. Un hook custom pour la logique métier
Chaque écran a son hook : useTaskDetail, useFeedScreen, useGroupScreen... Le hook encapsule toute la logique : chargement des données, gestion d'état, callbacks. Le composant ne fait que rendre du JSX.
Avant :
// TaskDetailScreen.tsx - 800 lignes
const TaskDetailScreen = () => {
const [task, setTask] = useState(null);
const [loading, setLoading] = useState(true);
const [editing, setEditing] = useState(false);
// ... 50 autres useState
// ... 200 lignes de useEffect
// ... 300 lignes de handlers
// ... 250 lignes de JSX
}
Après :
// TaskDetailScreen.tsx - 100 lignes
const TaskDetailScreen = () => {
const { task, loading, editing, handlers } = useTaskDetail();
return (
<TaskDetailHeader task={task} onEdit={handlers.edit} />
<TaskDetailBody task={task} />
<TaskDetailActions handlers={handlers} />
);
}
Le hook useTaskDetail fait 200 lignes. Les sous-composants font 50 à 100 lignes chacun. Au total, ça fait plus de lignes qu'avant — mais chaque fichier est compréhensible isolément.
2. Des sous-composants pour le rendu
Chaque section visuelle de l'écran devient un composant dédié : TaskDetailHeader, TaskDetailBody, TaskDetailActions. Chacun reçoit ses props et ne connaît que sa responsabilité.
Ce pattern est directement inspiré du Thinking in React officiel. Ce n'est pas nouveau, mais c'est incroyable à quel point on l'oublie quand on est pressé de livrer.
3. Un composant principal pour l'orchestration
Le composant principal devient un chef d'orchestre de 100 lignes : il appelle le hook, distribue les props aux sous-composants, et gère le layout global. Rien d'autre.
Comment passer de 71 à 0 erreurs ESLint ?
En parallèle du refactoring des écrans, j'ai lancé ESLint sur le backend avec des règles strictes. Résultat : 71 erreurs.
La tentation : désactiver les règles qui génèrent le plus d'erreurs. C'est ce que font 90% des développeurs. J'ai fait l'inverse : j'ai corrigé chaque erreur individuellement.
Les corrections les plus impactantes
Élimination des any : chaque any dans TypeScript est une bombe à retardement. Ça compile, ça passe les tests, mais ça crash en production quand une valeur inattendue arrive. J'ai remplacé chaque any par un type explicite. Certains cas ont nécessité de créer des interfaces dédiées, mais le résultat est un code auto-documenté.
Promesses correctement awaited : des appels asynchrones sans await qui échouaient silencieusement. Pas d'erreur, pas de warning — juste un comportement incorrect en production. ESLint a détecté 12 cas de promesses non-awaitées. 12 bugs potentiels éliminés en une heure.
Variables inutilisées : des imports oubliés, des variables déclarées puis jamais utilisées. Pas des bugs, mais du bruit qui rend le code plus difficile à lire. Chaque ligne inutile est une distraction pour le "toi du futur" qui essaie de comprendre le code.
Faut-il refactorer tout d'un coup ou progressivement ?
Progressivement. Toujours progressivement. Un "big bang refactoring" où tu réécris tout en une semaine, c'est la recette du désastre pour un dev solo. Tu casses tout, tu ne peux plus livrer, et si un bug critique arrive en production, tu ne peux pas le corriger rapidement.
Ma méthode :
- Choisir l'écran le plus douloureux (celui que tu dreades d'ouvrir)
- Extraire le hook custom en premier (la logique, pas le rendu)
- Tester que tout fonctionne encore exactement comme avant
- Extraire les sous-composants un par un
- Livrer l'écran refactoré, passer au suivant
Chaque écran refactoré prenait entre 2 heures et une demi-journée. Les plus complexes (le Feed, l'écran de groupe) ont pris une journée complète. Mais à chaque étape, l'app restait fonctionnelle et livrable.
Ce workflow est similaire à ce que Martin Fowler décrit dans son livre sur le refactoring : des transformations petites, incrémentales, et toujours réversibles.
Quels gains concrets après le refactoring ?
Après deux semaines de travail :
- 16 écrans refactorés : chacun suit le même pattern (hook + sous-composants + orchestrateur)
- 0 erreur ESLint sur le backend (contre 71 avant)
- Temps de compréhension divisé par 3 : ouvrir un écran et comprendre ce qu'il fait prend 2 minutes au lieu de 10
- Bugs réduits : les 3 semaines suivantes ont été les plus stables du projet
- Motivation retrouvée : ouvrir un fichier propre le matin, ça change tout
Le gain le moins mesurable mais le plus important : la confiance. Après le refactoring, je n'avais plus peur de modifier un écran. Je savais exactement où chaque chose se trouvait, quelles étaient les dépendances, et ce qu'un changement allait impacter.
Comment la dette technique affecte-t-elle un projet solo ?
La dette technique dans un projet solo a des effets spécifiques qu'on ne retrouve pas en équipe :
Pas de filet de sécurité. En équipe, un collègue peut relire ton code, détecter une régression, ou corriger un bug quand tu es absent. Seul, si ton code est incompréhensible, c'est toi — et toi seul — qui paies le prix.
L'effet composé. Chaque shortcut que tu prends aujourd'hui se multiplie. Un any ici, un // TODO: fix later là, et en quelques mois, tu as un codebase où chaque modification prend 3x plus de temps qu'elle ne devrait.
La spirale de démotivation. Code sale → bugs → frustration → patches rapides → code encore plus sale. J'ai vu cette spirale sur d'autres projets. Le refactoring l'a brisée nette.
C'est la même logique que j'applique à la restructuration de la base de données et à l'audit de sécurité : investir du temps maintenant pour en gagner exponentiellement plus tard.
Quelles règles ESLint recommander pour un projet React Native ?
Voici les règles qui ont eu le plus d'impact sur la qualité du code TAMSIV :
@typescript-eslint/no-explicit-any: interdit lesany. Non négociable.@typescript-eslint/no-floating-promises: détecte les promesses non-awaitées. Critique pour éviter les bugs silencieux.@typescript-eslint/no-unused-vars: élimine le bruit du code mort.react-hooks/exhaustive-deps: vérifie les dépendances des hooks. Essentiel en React Native.no-console: force à utiliser un logger plutôt queconsole.logen production.
Active-les toutes en mode "error", pas "warn". Un warning, ça s'ignore. Une erreur, ça se corrige.
Ce que j'ai appris de cette semaine de refactoring
Cette semaine a été la meilleure du projet. Pas la plus excitante — aucune feature visible pour l'utilisateur. Mais la plus impactante pour la suite. Chaque feature que j'ai construite après — le système de gamification, les groupes hiérarchiques, l'agenda collaboratif — a bénéficié de cette architecture propre.
Si tu es dev solo et que tu repousses un refactoring parce que "ça ne livre rien de visible", arrête. C'est l'investissement le plus rentable que tu puisses faire. Pas glamour, pas excitant, mais fondamentalement nécessaire.
La meilleure semaine du projet. Et je le répète sans hésiter.
FAQ
Combien de temps prend un refactoring de 16 écrans ?
Pour moi, environ deux semaines à temps plein. Chaque écran prend entre 2 heures et une journée selon sa complexité. L'écran le plus simple (un formulaire basique) : 2 heures. Le plus complexe (le Feed avec gamification) : une journée complète.
Le refactoring introduit-il de nouveaux bugs ?
C'est le risque principal. Pour le minimiser, je refactorais un écran à la fois et testais manuellement chaque flow avant de passer au suivant. Aucune régression majeure n'est apparue pendant les deux semaines de refactoring.
Faut-il écrire des tests avant de refactorer ?
Dans l'idéal, oui. En réalité, sur un projet solo avec 16 écrans à refactorer, écrire des tests exhaustifs avant le refactoring doublerait le temps. J'ai opté pour des tests manuels rigoureux et des tests automatisés après le refactoring, sur l'architecture propre.
Le pattern hook + sous-composants fonctionne-t-il pour tous les écrans ?
Oui, avec des variations. Certains écrans simples n'ont pas besoin de sous-composants — le hook seul suffit. D'autres écrans complexes ont plusieurs niveaux de sous-composants. Le principe reste le même : séparer logique et rendu.
ESLint ralentit-il le développement au quotidien ?
Les premières heures, oui — le temps de corriger les erreurs existantes. Ensuite, c'est l'inverse : ESLint accélère le développement en détectant les erreurs avant même de lancer l'app. C'est comme un copilote qui corrige ta trajectoire en temps réel.