Explorez les bonnes pratiques pour utiliser TypeScript avec React afin de créer des applications web robustes, évolutives et maintenables. Apprenez la structure de projet, la conception de composants, les tests et l'optimisation.
TypeScript avec React : Bonnes pratiques pour des applications évolutives et maintenables
TypeScript et React sont une combinaison puissante pour construire des applications web modernes. TypeScript apporte le typage statique à JavaScript, améliorant la qualité du code et la maintenabilité, tandis que React offre une approche déclarative et basée sur les composants pour construire des interfaces utilisateur. Ce billet de blog explore les meilleures pratiques pour utiliser TypeScript avec React afin de créer des applications robustes, évolutives et maintenables, adaptées à un public mondial.
Pourquoi utiliser TypeScript avec React ?
Avant de plonger dans les bonnes pratiques, comprenons pourquoi TypeScript est un ajout précieux au développement React :
- Amélioration de la qualité du code : Le typage statique de TypeScript permet de détecter les erreurs tôt dans le processus de développement, réduisant les problèmes d'exécution et améliorant la fiabilité du code.
- Maintenabilité améliorée : Les annotations de type et les interfaces rendent le code plus facile à comprendre et à refactoriser, conduisant à une meilleure maintenabilité à long terme.
- Meilleur support de l'IDE : TypeScript offre un excellent support de l'IDE, y compris l'autocomplétion, la navigation dans le code et les outils de refactorisation, augmentant la productivité des développeurs.
- Réduction des bugs : Le typage statique détecte de nombreuses erreurs JavaScript courantes avant l'exécution, ce qui permet d'obtenir une application plus stable et sans bugs.
- Amélioration de la collaboration : Des définitions de types claires facilitent la collaboration des équipes sur de grands projets, car les développeurs peuvent rapidement comprendre le but et l'utilisation des différents composants et fonctions.
Configuration d'un projet React TypeScript
Utiliser Create React App
Le moyen le plus simple de démarrer un nouveau projet React TypeScript est d'utiliser Create React App avec le modèle TypeScript :
npx create-react-app my-typescript-react-app --template typescript
Cette commande configure un projet React de base avec TypeScript, y compris les dépendances nécessaires et un fichier tsconfig.json
.
Configuration de tsconfig.json
Le fichier tsconfig.json
est le cœur de votre configuration TypeScript. Voici quelques paramètres recommandés :
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
Options clés à considérer :
"strict": true
: Active la vérification stricte des types, ce qui est fortement recommandé pour détecter les erreurs potentielles."esModuleInterop": true
: Permet l'interopérabilité entre les modules CommonJS et ES."jsx": "react-jsx"
: Active le nouveau transform JSX, qui simplifie le code React et améliore les performances.
Bonnes pratiques pour les composants React avec TypeScript
Typage des props des composants
L'un des aspects les plus importants de l'utilisation de TypeScript avec React est de typer correctement les props de vos composants. Utilisez des interfaces ou des alias de type pour définir la structure de l'objet props.
interface MyComponentProps {
name: string;
age?: number; // Prop optionnelle
onClick: () => void;
}
const MyComponent: React.FC<MyComponentProps> = ({ name, age, onClick }) => {
return (
Bonjour, {name} !
{age && Vous avez {age} ans.
}
);
};
L'utilisation de React.FC<MyComponentProps>
garantit que le composant est un composant fonctionnel et que les props sont correctement typées.
Typage de l'état du composant
Si vous utilisez des composants de classe, vous devrez également typer l'état du composant. Définissez une interface ou un alias de type pour l'objet d'état et utilisez-le dans la définition du composant.
interface MyComponentState {
count: number;
}
class MyComponent extends React.Component<{}, MyComponentState> {
state: MyComponentState = {
count: 0
};
handleClick = () => {
this.setState({
count: this.state.count + 1
});
};
render() {
return (
Compteur : {this.state.count}
);
}
}
Pour les composants fonctionnels utilisant le hook useState
, TypeScript peut souvent déduire le type de la variable d'état, mais vous pouvez également le fournir explicitement :
import React, { useState } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState<number>(0);
return (
Compteur : {count}
);
};
Utilisation des Type Guards
Les Type Guards sont des fonctions qui restreignent le type d'une variable dans un champ d'application spécifique. Ils sont utiles lors de la gestion de types union ou lorsque vous devez vous assurer qu'une variable a un type spécifique avant d'effectuer une opération.
interface Circle {
kind: "circle";
radius: number;
}
interface Square {
kind: "square";
side: number;
}
type Shape = Circle | Square;
function isCircle(shape: Shape): shape is Circle {
return shape.kind === "circle";
}
function getArea(shape: Shape): number {
if (isCircle(shape)) {
return Math.PI * shape.radius ** 2;
} else {
return shape.side ** 2;
}
}
La fonction isCircle
est un Type Guard qui vérifie si une Shape
est un Circle
. Dans le bloc if
, TypeScript sait que shape
est un Circle
et vous permet d'accéder à sa propriété radius
.
Gestion des événements
Lors de la gestion des événements dans React avec TypeScript, il est important de typer correctement l'objet événement. Utilisez le type d'événement approprié de l'espace de noms React
.
const MyComponent: React.FC = () => {
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
console.log(event.target.value);
};
return (
<input type="text" onChange={handleChange} />
);
};
Dans cet exemple, React.ChangeEvent<HTMLInputElement>
est utilisé pour typer l'objet événement pour un événement de changement sur un élément d'entrée. Cela donne accès à la propriété target
, qui est un HTMLInputElement
.
Structure du projet
Une structure de projet bien organisée est cruciale pour la maintenabilité et l'évolutivité. Voici une structure de projet suggérée pour une application React TypeScript :
src/
├── components/
│ ├── MyComponent/
│ │ ├── MyComponent.tsx
│ │ ├── MyComponent.module.css
│ │ └── index.ts
├── pages/
│ ├── HomePage.tsx
│ └── AboutPage.tsx
├── services/
│ ├── api.ts
│ └── auth.ts
├── types/
│ ├── index.ts
│ └── models.ts
├── utils/
│ ├── helpers.ts
│ └── constants.ts
├── App.tsx
├── index.tsx
├── react-app-env.d.ts
└── tsconfig.json
Points clés :
- Composants : Groupez les composants connexes dans des répertoires. Chaque répertoire doit contenir le fichier TypeScript du composant, les modules CSS (si utilisés) et un fichier
index.ts
pour exporter le composant. - Pages : Stockez les composants de niveau supérieur qui représentent différentes pages de votre application.
- Services : Implémentez les appels API et autres services dans ce répertoire.
- Types : Définissez les définitions de type globales et les interfaces dans ce répertoire.
- Utils : Stockez les fonctions utilitaires et les constantes.
- index.ts : Utilisez les fichiers
index.ts
pour réexporter les modules d'un répertoire, fournissant une API propre et organisée pour importer les modules.
Utilisation des Hooks avec TypeScript
Les Hooks React vous permettent d'utiliser l'état et d'autres fonctionnalités React dans les composants fonctionnels. TypeScript fonctionne parfaitement avec les Hooks, offrant une sécurité de type et une expérience de développeur améliorée.
useState
Comme montré précédemment, vous pouvez typer explicitement la variable d'état lors de l'utilisation de useState
:
import React, { useState } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState<number>(0);
return (
Compteur : {count}
);
};
useEffect
Lors de l'utilisation de useEffect
, soyez attentif au tableau de dépendances. TypeScript peut vous aider à détecter les erreurs si vous oubliez d'inclure une dépendance utilisée dans l'effet.
import React, { useState, useEffect } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState<number>(0);
useEffect(() => {
document.title = `Compteur : ${count}`;
}, [count]); // Ajoutez 'count' au tableau des dépendances
return (
Compteur : {count}
);
};
Si vous omettez count
du tableau de dépendances, l'effet ne s'exécutera qu'une seule fois au montage du composant, et le titre du document ne sera pas mis à jour lorsque le compteur changera. TypeScript vous avertira de ce problème potentiel.
useContext
Lors de l'utilisation de useContext
, vous devez fournir un type pour la valeur du contexte.
import React, { createContext, useContext } from 'react';
interface ThemeContextType {
theme: string;
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
const ThemeProvider: React.FC = ({ children }) => {
// Implémentez la logique du thème ici
return (
{} }}>
{children}
);
};
const MyComponent: React.FC = () => {
const { theme, toggleTheme } = useContext(ThemeContext) as ThemeContextType;
return (
Thème : {theme}
);
};
export { ThemeProvider, MyComponent };
En fournissant un type pour la valeur du contexte, vous vous assurez que le hook useContext
renvoie une valeur du bon type.
Tester les composants React TypeScript
Les tests sont une partie essentielle de la construction d'applications robustes. TypeScript améliore les tests en fournissant une sécurité de type et une couverture de code améliorée.
Tests unitaires
Utilisez des frameworks de test comme Jest et React Testing Library pour tester unitairement vos composants.
// MyComponent.test.tsx
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
it('rend le composant avec le nom correct', () => {
render(<MyComponent name="John" />);
expect(screen.getByText('Bonjour, John !')).toBeInTheDocument();
});
it('appelle le gestionnaire onClick lors du clic sur le bouton', () => {
const onClick = jest.fn();
render(<MyComponent name="John" onClick={onClick} />);
fireEvent.click(screen.getByRole('button'));
expect(onClick).toHaveBeenCalledTimes(1);
});
});
La vérification des types de TypeScript aide à détecter les erreurs dans vos tests, comme le passage de props incorrectes ou l'utilisation de gestionnaires d'événements erronés.
Tests d'intégration
Les tests d'intégration vérifient que différentes parties de votre application fonctionnent correctement ensemble. Utilisez des outils comme Cypress ou Playwright pour les tests de bout en bout.
Optimisation des performances
TypeScript peut également aider à l'optimisation des performances en détectant les goulots d'étranglement potentiels au début du processus de développement.
Mémorisation
Utilisez React.memo
pour mémoriser les composants fonctionnels et éviter les rendus inutiles.
import React from 'react';
interface MyComponentProps {
name: string;
}
const MyComponent: React.FC<MyComponentProps> = ({ name }) => {
console.log('Rendu de MyComponent');
return (
<p>Bonjour, {name} !</p>
);
};
export default React.memo(MyComponent);
React.memo
ne rendra le composant que si les props ont changé. Cela peut améliorer considérablement les performances, en particulier pour les composants complexes.
Fractionnement du code
Utilisez les importations dynamiques pour fractionner votre code en morceaux plus petits et les charger à la demande. Cela peut réduire le temps de chargement initial de votre application.
import React, { Suspense } from 'react';
const MyComponent = React.lazy(() => import('./MyComponent'));
const App: React.FC = () => {
return (
<Suspense fallback={Chargement...}>
<MyComponent />
</Suspense>
);
};
React.lazy
vous permet d'importer dynamiquement des composants, qui ne sont chargés que lorsqu'ils sont nécessaires. Le composant Suspense
fournit une interface utilisateur de secours pendant le chargement du composant.
Conclusion
L'utilisation de TypeScript avec React peut améliorer considérablement la qualité, la maintenabilité et l'évolutivité de vos applications web. En suivant ces bonnes pratiques, vous pouvez tirer parti de la puissance de TypeScript pour créer des applications robustes et performantes qui répondent aux besoins d'un public mondial. N'oubliez pas de vous concentrer sur des définitions de types claires, une organisation de projet bien structurée et des tests approfondis pour assurer le succès à long terme de vos projets.