Comment j'organise mes projets Typescript (partie 2)

Comment j'organise mes projets Typescript (partie 2)
Alexandre P. dans Dev - mis à jour le 29-04-2025

Optimisez vos projets React/Next.js avec une architecture DRY, des hooks organisés et l'efficacité TypeScript. Gagnez en qualité et en productivité !

Cela fait maintenant 9 ans que j'utilise React, j'ai commencé à l'époque en class component et j'ai migré petit à petit vers le functional que je préfère de loin par sa simplicité.

Mais j'ai vu ce langage évoluer et devenir ce qu'il est aujourd'hui, en passant par des phases où il s'est complexifié puis de nouveau simplifié.

Aujourd'hui, on peut exploiter réellement la puissance de React lorsqu'il est couplé à Typescript.

Beaucoup de développeurs pensent que Typescript complique le développement, or, pour des développeurs très avancés, il simplifie tout.

  • La correction en temps réel des erreurs via tsc, lint
  • La robustesse des livrables tant on travaille en territoire connu
  • Une anticipation des comportements

Mes conseils d'Expert Next.js

Revenir à JS pour un développeur avancé, c'est comme si tu disais à quelqu'un qui a une voiture de repasser sur un cheval... De la perte de temps !

Typescript est un langage que j'ai adopté un peu plus tard, en 2018/2019 via des apps mobiles.

J'y suis revenu ensuite en 2021 définitivement sans aucun retour en arrière possible tellement cet outil est riche de possibilités.

Je vais vous partager aujourd'hui, comme suite de mon article sur l'organisation Typescript , des conseils qui font de moi un Expert React, Next.js avec plus de 20 projets déployés, des dizaines de millions d'ARR générés pour mes clients.

L'expérience du code c'est une chose, l'expérience de la production sur des projets qui ramènent de l'argent en est une autre. Si je me trompe dans mes choix, c'est un impact direct sur les revenus de mes clients, c'est pourquoi j'ai fait le choix d'outils robustes et de méthodologies rigoureuses.

La pratique du DRY

Qui n'a jamais travaillé sur un projet où l'on redéclare exactement les mêmes requêtes sur chaque pages pour récupérer les utilisateurs, ou encore pour récupérer les produits que ce soit sur une liste, une liste filtrée, une fiche produit, une liste des commandes avec détail produits, etc...

Il y a exactement les mêmes requêtes et on se répète encore et encore.

Pire, si on nous demande de modifier la moindre chose, il faut repasser sur absolument toutes les pages pour répéter la modification et il suffira d'un oubli pour commencer à créer des écarts de comportement et casser l'app. Aujourd'hui je vais vous proposer une approche totalement DRY compliant, qui a été testé sur de multiples projets et fait ses preuves.

L'organisation de requêtes en hook React

Alors bien sûr, il faut commencer par utiliser un outil de requête, j'utilise React-Query depuis quelques années déjà, mais je pense que tout autre outil comme SWR etc peut aussi faire l'affaire.

Assurez vous simplement que vous avez un système de caching pour tirer profit de tout cela. React-Query a une approche clé de cache qui vous permet de ne pas refaire un appel back si vous faites plusieurs fois le même appel pendant le rendu (ex: 2 composants qui ont besoin du même jeu de données).

Une fois que vous aurez fait tout le travail de base de mise en place avec le Provider de React-Query (que vous pouvez tout simplement mettre en place en suivant le guide ) nous allons nous pencher sur l'organisation de nos requêtes.

L'arborescence

Je l'ai déjà dit plus haut mais, une requête = un hook, on va se contenter de faire simple. Et pour une meilleure organisation des hooks, je crée une arborescence comme ceci:

/hooks
|
|__ /users
|    |__ useListUsers.tsx
|    |__ useGetUser.tsx
|    |__ useSaveUser.tsx
|    |__ useDeleteUser.tsx
|
|__ /products
|    |__ useListProducts.tsx
|    |__ useGetProduct.tsx
|    |__ useSaveProduct.tsx
|    |__ useDeleteProduct.tsx

Comme vous pouvez le voir j'effectue un découpage des requêtes par model afin de s'y retrouver plus facilement quand on va importer notre hook.

Le nommage des hooks

Comme vous pouvez le voir, j'ai une règle de nommage pour mes hooks. Cela me permet de savoir le type de résultat qu'est sensé renvoyer mon hook:

  • useList... : le hook renvoie un array
  • useGet... : le hook renvoie un objet
  • useSave... : est un hook de mutation qui passera de create à update en fonction d'un ID que je passerai en argument
  • useDelete... : le hook de mutation qui sert à faire des suppression

L'utilisation des hooks

Les développeurs React savent que les hooks s'utilisent en entrée de page, (de toute façon on ne peut pas l'utiliser après avoir commencer à faire de la logique comme des conditions etc...).

Cela signifie que la première chose que fait mon composant, c'est de déclencher les appels pour récupérer de la donnée.

Oui, votre composant n'a pas encore reçu la réponse, mais pas de panique, un useQuery sur React-Query permet toujours d'avoir un état de la requête.

const { data, isLoading } = useGetUser()

// Au 1er run du composant data est vide car il n'a pas encore reçu la réponse du backend
// on utilisera isLoading pour montrer cet état

return (
  <>
     {isLoading ? <Spinner /> : <UserComponent user={data} />} 
  </>
)

En ce qui concerne les mutations, donc les requêtes de type écriture: ajout, modification ou encore suppression, on va procéder différemment.

On sait déjà que tout ce qui est écriture est asynchrone dans une logique de page web.

Un utilisateur effectue toujours une action avant un appel de type POST, PUT, DELETE.

S'il s'agit d'un formulaire de connexion par exemple:

const loginAction = usePostLogin() // Ici, usePostLogin est un useMutation de React-Query
const router = useRouter()
const { handleSubmit, register, formState } = useForm<LoginForm>() // useForm vient de React-Hook-Form

const onSubmit = (login: LoginForm) => {
  loginAction.mutate(login, {
    onSuccess: () => {
      toast.success('Welcome')
      router.push('/')
    },
    onError: () => toast.error('Something went wrong')
  })
}

return (
  <>
     <form onSubmit={handleSumit(onSubmit)}>
       <input type="text" {...register('username')} />
       <input type="password" {...register('password')} />
       <button type="submit">Sign in</button>
     </form>
  </>
)

Ici c'est l'action de submit le formulaire qui va déclencher notre mutation via le hook.

Mais l'organisation via des hooks me permet de déplacer cette logique de page en page facilement.

De même quand j'ai un soucis avec un appel, je sais exactement dans quel composant je dois effectuer mes modifications étant donné mon organisation.

Une meilleure organisation frontend

En appliquant ces principes simples mais puissants, vous allez gagner en lisibilité, en maintenance et surtout en scalabilité sur vos projets React/Next.js.

Croyez-en mon expérience : une architecture claire et DRY fait toute la différence quand il s'agit de livrer vite, proprement, et sans surprises en production.

Le code, c'est avant tout un métier d'anticipation : préparez vos bases sérieusement, et vos projets vous remercieront.

#typescript#react#methodologie

user picture

Alexandre P.

Développeur passionné depuis plus de 20 ans, j'ai une appétence particulière pour les défis techniques et changer de technologie ne me fait pas froid aux yeux.


Votre vie privée

Nous utilisons des cookies pour améliorer votre expérience sur notre site, analyser notre trafic et personnaliser les publicités. En cliquant sur "Accepter", vous consentez à l'utilisation de tous les cookies. Vous pouvez également choisir de refuser en cliquant sur le bouton "Refuser".