Aller au contenu

React • Premiers pas

Dans cet article, nous allons créer un nouveau projet React à l’aide de Vite.

Nous allons ensuite parcourir chaque fichier afin de comprendre à quoi il sert, comment il fonctionne.

React est une « bibliothèque pour des interfaces utilisateurs web et natives ». Cette bibliothèque permet la « création d’interfaces utilisateurs à l’aide de composants ».

React va nous permettre de découper notre interface utilisateur en blocs individuels. Ces blocs sont appelés « composants ». Un composant peut être :

  • une page entière ;
  • une portion de page (en-tête de page, pied de page, menu, navigation, section, etc.) ;
  • un élément d’UI (un bouton, un lien, une carte, un like, etc.).

Vite est un outil qui va nous permettre de :

  • transpiler/compiler notre code source en fichiers exécutables par un navigateur web ;
  • démarrer un serveur web ;
  • mettre à jour instantanément la page du navigateur à chaque modification de notre code ;
  • et build le projet en fichiers optimisés une fois notre développement terminé.

Suivons le guide proposé par Vite pour créer notre projet React. Plaçons-nous dans le dossier de notre choix et ouvrons un terminal.

Fenêtre de terminal
npm create vite@latest

Suivons les étapes en répondant aux questions :

  • Ok to proceed? (y)y ;
  • ? Project name: »react-project ;
  • ? Select a framework: »React ;
  • ? Select a variant: »TypeScript.

Une fois le projet créé, suivons les instructions.

Fenêtre de terminal
cd react-project
npm install
npm run dev

Voici la structure du projet :

  • RépertoireREACT-PROJECT
    • Répertoirenode_modules/
    • Répertoirepublic/
      • vite.svg
    • Répertoiresrc/
      • Répertoireassets/
        • react.svg
      • App.css
      • App.tsx
      • index.css
      • main.tsx
      • vite-end.d.ts
    • .eslintrc.cjs
    • .gitignore
    • index.html
    • package-lock.json
    • package.json
    • README.md
    • tsconfig.app.json
    • tsconfig.json
    • tsconfig.node.json
    • vite.config.ts

Nous allons maintenant parcourir les fichiers et les dossiers de notre projet.

Faisons d’abord le tour des fichiers de configuration de notre projet React.

  • RépertoireREACT-PROJECT
    • Répertoirenode_modules/
    • Répertoirepublic/
      • vite.svg
    • Répertoiresrc/
      • Répertoireassets/
        • react.svg
      • App.css
      • App.tsx
      • index.css
      • main.tsx
      • vite-end.d.ts
    • .eslintrc.cjs
    • .gitignore
    • index.html
    • package-lock.json
    • package.json
    • README.md
    • tsconfig.app.json
    • tsconfig.json
    • tsconfig.node.json
    • vite.config.ts
package.json
{
"name": "react-project",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.13.1",
"@typescript-eslint/parser": "^7.13.1",
"@vitejs/plugin-react": "^4.3.1",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"typescript": "^5.2.2",
"vite": "^5.3.1"
}
}
  • name : Nom du projet ;
  • private : Un projet privé ne peut être publié sur npm Registry ;
  • version : Version du projet ;
  • scripts : Liste des scripts exécutables via npm run <script> ;
  • dependencies : Liste des dépendances nécessaires et livrées lors de la phase de build ;
  • devDependencies : Liste des dépendances utilisées en phase de développement, mais non livrées lors du build.

La section dependencies liste deux dépendances : react et react-dom.

La dépendance react contient les fonctionnalités nécessaires pour créer des composants React. Elle doit être associée à un moteur de rendu :

Les dépendances listées sous la section devDependencies peuvent être regroupées en plusieurs catégories :

  • la librairie TypeScript : typescript ;
  • les définitions de types pour Typescript : @types/react, @types/react-dom ;
  • la librairie Vite et ses plugins : vite, @vitejs/plugin-react ;
  • le linter ESLint et ses plugins : eslint, eslint-plugin-react-hooks, @typescript-eslint/eslint-plugin, etc.
  • RépertoireREACT-PROJECT
    • Répertoirenode_modules/
    • Répertoirepublic/
      • vite.svg
    • Répertoiresrc/
      • Répertoireassets/
        • react.svg
      • App.css
      • App.tsx
      • index.css
      • main.tsx
      • vite-end.d.ts
    • .eslintrc.cjs
    • .gitignore
    • index.html
    • package-lock.json
    • package.json
    • README.md
    • tsconfig.app.json
    • tsconfig.json
    • tsconfig.node.json
    • vite.config.ts
.eslintrc.cjs
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}

Ce fichier permet de paramétrer le linter ESLint.

  • RépertoireREACT-PROJECT
    • Répertoirenode_modules/
    • Répertoirepublic/
      • vite.svg
    • Répertoiresrc/
      • Répertoireassets/
        • react.svg
      • App.css
      • App.tsx
      • index.css
      • main.tsx
      • vite-end.d.ts
    • .eslintrc.cjs
    • .gitignore
    • index.html
    • package-lock.json
    • package.json
    • README.md
    • tsconfig.app.json
    • tsconfig.json
    • tsconfig.node.json
    • vite.config.ts
tsconfig.app.json
{
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}

La configuration TypeScript est un vaste sujet qui mériterait un article à part entière. Voici néanmoins quelques paramètres à retenir :

  • lib : les définitions de types et leurs versions (DOM, DOM.Iterable, ScriptHost, WebWorker, ES2015, ES2016, ES2017, etc. ) ;
  • module : la version d’ECMAScript utilisée en phase de développement (ESNext = version la plus récente) ;
  • target : la version cible d’ECMAScript lors de la phase de build ;
  • strict : active une série d’options de vérifications de type afin d’améliorer la fiabilité et la qualité du code ;
  • noUnusedLocals, noUnusedParameters, noFallthroughCasesInSwitch : paramètres supplémentaires permettant d’améliorer la fiabilité et la qualité du code.
  • RépertoireREACT-PROJECT
    • Répertoirenode_modules/
    • Répertoirepublic/
      • vite.svg
    • Répertoiresrc/
      • Répertoireassets/
        • react.svg
      • App.css
      • App.tsx
      • index.css
      • main.tsx
      • vite-end.d.ts
    • .eslintrc.cjs
    • .gitignore
    • index.html
    • package-lock.json
    • package.json
    • README.md
    • tsconfig.app.json
    • tsconfig.json
    • tsconfig.node.json
    • vite.config.ts
vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
})

Ce fichier permet de configurer Vite. Le plugin react est ajouté, permettant à Vite de « parler » le langage react. Ainsi Vite est capable de comprendre react, détecter les erreurs et compiler du code source react en javascript natif.

Analysons ensuite les fichiers de code.

  • RépertoireREACT-PROJECT
    • Répertoirenode_modules/
    • Répertoirepublic/
      • vite.svg
    • Répertoiresrc/
      • Répertoireassets/
        • react.svg
      • App.css
      • App.tsx
      • index.css
      • main.tsx
      • vite-end.d.ts
    • .eslintrc.cjs
    • .gitignore
    • index.html
    • package-lock.json
    • package.json
    • README.md
    • tsconfig.app.json
    • tsconfig.json
    • tsconfig.node.json
    • vite.config.ts
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

Ce fichier HTML est le point d’entrée de notre application React.

<link rel="icon" type="image/svg+xml" href="/vite.svg" /> utilise le fichier vite.svg stocké dans le dossier public/.

Le body contient :

  • un élément <div> avec l’identifiant root ;
  • une balise <script> ayant pour source le fichier main.tsx.
  • RépertoireREACT-PROJECT
    • Répertoirenode_modules/
    • Répertoirepublic/
      • vite.svg
    • Répertoiresrc/
      • Répertoireassets/
        • react.svg
      • App.css
      • App.tsx
      • index.css
      • main.tsx
      • vite-end.d.ts
    • .eslintrc.cjs
    • .gitignore
    • index.html
    • package-lock.json
    • package.json
    • README.md
    • tsconfig.app.json
    • tsconfig.json
    • tsconfig.node.json
    • vite.config.ts
main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)

Que se passe-t-il ici ?

  1. document.getElementById('root') : retourne l’élément du DOM avec l’identifiant root ;
  2. ReactDOM.createRoot() : permet d’associer un élément du DOM à un composant React ;
  3. render(<App />) : rends le composant React App dans l’élément du DOM.

<div id="root" /><App />

Il est ainsi possible d’associer un élément du DOM à un composant React. Nous pouvons créer plusieurs associations si besoin.

De plus, le fichier index.css est importé. Cela permet d’appliquer tout le CSS déclaré dans ce fichier à l’ensemble de site.

Arrêtons-nous un moment sur la syntaxe utilisée.

JSX est une extension de syntaxe pour Javascript qui permet d’écrire du code ressemblant à du HTML à l’intérieur d’un fichier Javascript. Nous pouvons ainsi utiliser des balises HTML standards et des balises représentant des composants React.

Les attributs de ces balises sont la plupart du temps identiques à deux de la balise HTML, à quelques exceptions :

  • classclassName
  • événements onclickonClick

En général le camelCase est utilisé pour les attributs, à quelques exceptions près.

  • RépertoireREACT-PROJECT
    • Répertoirenode_modules/
    • Répertoirepublic/
      • vite.svg
    • Répertoiresrc/
    • Répertoireassets/
      • react.svg
      • App.css
      • App.tsx
      • index.css
      • main.tsx
      • vite-end.d.ts
    • .eslintrc.cjs
    • .gitignore
    • index.html
    • package-lock.json
    • package.json
    • README.md
    • tsconfig.app.json
    • tsconfig.json
    • tsconfig.node.json
    • vite.config.ts
App.tsx
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
}
export default App

Voici enfin un composant React !

Un composant React est une fonction qui retourne un (seul et unique) élément. Ici l’élément retourné est : <> ... </>. C’est le raccourci pour Fragment : <Fragment> ... </Fragement>. Un fragment permet de regrouper plusieurs éléments, sans générer de balise HTML. Il est utile ici pour respecter la règle énoncée juste avant.

À l’intérieur de ce fragment, nous avons du code ressemblant à du HTML. C’est tout l’intérêt de la syntaxe JSX.

Regardons maintenant le code du bouton : <button onClick={() => setCount((count) => count + 1)}>. L’événement click du bouton est associé à la fonction : () => setCount((count) => count + 1). La fonction setCount() est déclarée ici  : const [count, setCount] = useState(0). useState() est une fonction fournie par la librairie React. Cette fonction est un Hook.

Les Hooks sont des fonctions fournies par React qui apportent des fonctionnalités au sein des composants.

Quel genre de fonctionnalités apportent les Hooks ? React propose les groupes suivants :

Nous reviendrons en détail sur quelques hooks souvent utilisés.

Le hook useState créé une variable d’état dans notre composant.

useState
const [state, setState] = useState(initialState);

Le hook useState() retourne un tableau de deux élements :

  1. La valeur courante de l’état ;
  2. Une fonction permettant de mettre à jour l’état.

Pourquoi avons-nous besoin de ce hook ?

Modifions le code afin de remplacer le hook par une variable counter.

App.tsx
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
function App() {
const [count, setCount] = useState(0)
let counter = 0
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
<button onClick={() => counter++}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
}
export default App

Après avoir rafraichi la page dans le navigateur, nous remarquons que le bouton n’incrémente plus le compteur. Pourquoi ?

À chaque rendu d’un composant, React appelle la fonction correspondante. Et le clic sur le bouton déclenche un nouveau rendu. La variable counter ainsi déclarée dans la fonction App() a pour valeur 0. Elle aura toujours cette valeur puisqu’elle est recréée à chaque rendu, donc à chaque clic.

Le hook useState permet de résoudre ce problème en conservant la valeur de l’état entre deux rendus.

Le projet React de départ proposé par Vite nous a permis de beaucoup apprendre. Nous avons ainsi pu voir ensemble :

  • comment paramétrer un projet : dépendances npm, bundler Vite, linter ESLint, configuration TypeScript ;
  • comment un composant React est ajouté à une page HTML ;
  • comment est construit un composant React.

Mais ce n’est que le début, il reste encore beaucoup de choses à découvrir !