From 91d51bdef84a8cea6f53e8d10baefcf7c0d5f79a Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Wed, 26 Jul 2023 15:22:50 +0200 Subject: [PATCH 1/6] chore(nav): translate home sidebar (mobile) --- src/sidebarHome.json | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/sidebarHome.json b/src/sidebarHome.json index 1a8367114..e6c0d6899 100644 --- a/src/sidebarHome.json +++ b/src/sidebarHome.json @@ -4,10 +4,10 @@ "routes": [ { "hasSectionHeader": true, - "sectionHeader": "GET STARTED" + "sectionHeader": "DÉMARRAGE" }, { - "title": "Quick Start", + "title": "Démarrage rapide", "path": "/learn" }, { @@ -16,10 +16,10 @@ }, { "hasSectionHeader": true, - "sectionHeader": "LEARN REACT" + "sectionHeader": "APPRENDRE REACT" }, { - "title": "Describing the UI", + "title": "Décrire l’UI", "path": "/learn/describing-the-ui" }, { @@ -27,67 +27,67 @@ "path": "/learn/adding-interactivity" }, { - "title": "Managing State", + "title": "Gérer l'état", "path": "/learn/managing-state" }, { - "title": "Escape Hatches", + "title": "Échappatoires", "path": "/learn/escape-hatches" }, { "hasSectionHeader": true, - "sectionHeader": "REACT API" + "sectionHeader": "API REACT" }, { "title": "Hooks", "path": "/reference/react" }, { - "title": "Components", + "title": "Composants", "path": "/reference/react/components" }, { - "title": "APIs", + "title": "Fonctions", "path": "/reference/react/apis" }, { - "title": "Legacy APIs", + "title": "API React historique", "path": "/reference/react/legacy" }, { "hasSectionHeader": true, - "sectionHeader": "REACT DOM API" + "sectionHeader": "API REACT DOM" }, { - "title": "Components", + "title": "Composants", "path": "/reference/react-dom/components" }, { - "title": "APIs", + "title": "Fonctions", "path": "/reference/react-dom" }, { - "title": "Client APIs", + "title": "Fonctions côté client", "path": "/reference/react-dom/client" }, { - "title": "Server APIs", + "title": "Fonctions côté serveur", "path": "/reference/react-dom/server" }, { "hasSectionHeader": true, - "sectionHeader": "GET INVOLVED" + "sectionHeader": "S’IMPLIQUER" }, { - "title": "React Community", + "title": "Communauté React", "path": "/community" }, { "hasSectionHeader": true, - "sectionHeader": "STAY INFORMED" + "sectionHeader": "RESTER INFORMÉ·E" }, { - "title": "React Blog", + "title": "Blog React", "path": "/blog" } ] From fa9cbfafddc40e0efa48d3ab964cfdb0e97fa107 Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Wed, 26 Jul 2023 15:45:45 +0200 Subject: [PATCH 2/6] copy(tutorial): translate until overview --- src/content/learn/tutorial-tic-tac-toe.md | 118 +++++++++++----------- src/sidebarLearn.json | 2 +- 2 files changed, 61 insertions(+), 59 deletions(-) diff --git a/src/content/learn/tutorial-tic-tac-toe.md b/src/content/learn/tutorial-tic-tac-toe.md index 28d997b04..a9876ea0f 100644 --- a/src/content/learn/tutorial-tic-tac-toe.md +++ b/src/content/learn/tutorial-tic-tac-toe.md @@ -1,31 +1,33 @@ --- -title: 'Tutorial: Tic-Tac-Toe' +title: 'Tutoriel : Tic-Tac-Toe' --- -You will build a small tic-tac-toe game during this tutorial. This tutorial does not assume any existing React knowledge. The techniques you'll learn in the tutorial are fundamental to building any React app, and fully understanding it will give you a deep understanding of React. +Dans ce tutoriel, vous allez construire un petit jeu de tic-tac-toe. Ce tutoriel ne requiert aucune connaissance préalable de React. Les techniques que vous apprendrez dans ce tutoriel sont fondamentales pour construire n'importe quelle appli React : bien les comprendre vous donnera une compréhension profonde de React. -This tutorial is designed for people who prefer to **learn by doing** and want to quickly try making something tangible. If you prefer learning each concept step by step, start with [Describing the UI.](/learn/describing-the-ui) +Ce tutoriel est conçu pour les personnes qui préfèrent **apprendre en faisant** et qui veulent essayer de produire rapidement quelque chose de concret. Si vous préférez apprendre chaque concept pas à pas, commencez à la page [Décrire l'UI](/learn/describing-the-ui). -The tutorial is divided into several sections: +Ce tutoriel est découpé en plusieurs sections : -- [Setup for the tutorial](#setup-for-the-tutorial) will give you **a starting point** to follow the tutorial. -- [Overview](#overview) will teach you **the fundamentals** of React: components, props, and state. -- [Completing the game](#completing-the-game) will teach you **the most common techniques** in React development. -- [Adding time travel](#adding-time-travel) will give you **a deeper insight** into the unique strengths of React. +- [Se préparer au tutoriel](#setup-for-the-tutorial) vous donnera **un point de départ** pour le tutoriel. +- [Survol](#overview) vous apprendra **les fondamentaux** de React : composants, props et état. +- [Finaliser le jeu](#completing-the-game) vous apprendra **les techniques les plus courantes** du développement React. +- [Voyager dans le temps](#adding-time-travel) vous donnera **une meilleure perception** des avantages uniques de React. -### What are you building? {/*what-are-you-building*/} +### Qu'allez-vous construire ? {/*what-are-you-building*/} -In this tutorial, you'll build an interactive tic-tac-toe game with React. +Dans ce tutoriel, vous allez construire un jeu de tic-tac-toe interactif avec React. -You can see what it will look like when you're finished here: +*(Le tic-tac-toe est souvent appelé « morpion » en français, même si ce dernier n'est en fait pas limité à 3 × 3 cases, NdT.)* + +Vous pouvez voir à quoi ça ressemblera une fois terminé ci-dessous : @@ -57,9 +59,9 @@ function Board({ xIsNext, squares, onPlay }) { const winner = calculateWinner(squares); let status; if (winner) { - status = 'Winner: ' + winner; + status = 'Gagnant·e : ' + winner; } else { - status = 'Next player: ' + (xIsNext ? 'X' : 'O'); + status = 'Prochain tour : ' + (xIsNext ? 'X' : 'O'); } return ( @@ -103,9 +105,9 @@ export default function Game() { const moves = history.map((squares, move) => { let description; if (move > 0) { - description = 'Go to move #' + move; + description = 'Aller au coup #' + move; } else { - description = 'Go to game start'; + description = 'Revenir au début'; } return (
  • @@ -194,15 +196,15 @@ body { -If the code doesn't make sense to you yet, or if you are unfamiliar with the code's syntax, don't worry! The goal of this tutorial is to help you understand React and its syntax. +Si le code vous paraît incompréhensible, ou si des éléments de syntaxe vous semblent étranges, ne vous inquiétez pas ! L'objectif de ce tutoriel, c'est justement de vous aider à comprendre React et sa syntaxe. -We recommend that you check out the tic-tac-toe game above before continuing with the tutorial. One of the features that you'll notice is that there is a numbered list to the right of the game's board. This list gives you a history of all of the moves that have occurred in the game, and it is updated as the game progresses. +Nous vous conseillons de manipuler le jeu de tic-tac-toe ci-dessus avant de continuer ce tutoriel. Une des fonctionnalités que vous pourrez remarquer, c'est la liste numérotée des coups à droite du plateau de jeu. Elle vous donne un historique de tous les coups joués lors de la partie, mise à jour au fil du temps. -Once you've played around with the finished tic-tac-toe game, keep scrolling. You'll start with a simpler template in this tutorial. Our next step is to set you up so that you can start building the game. +Lorsque vous aurez fini de vous amuser avec ce jeu de tic-tac-toe finalisé, reprenez votre lecture de la page. Pour ce tutoriel, vous commencerez avec un gabarit simple. Notre prochaine étape consiste à vous préparer pour commencer à construire le jeu. -## Setup for the tutorial {/*setup-for-the-tutorial*/} +## Se préparer au tutoriel {/*setup-for-the-tutorial*/} -In the live code editor below, click **Fork** in the top-right corner to open the editor in a new tab using the website CodeSandbox. CodeSandbox lets you write code in your browser and preview how your users will see the app you've created. The new tab should display an empty square and the starter code for this tutorial. +Dans l'éditeur de code interactif ci-dessous, cliquez sur **Fork** en haut à droite pour ouvrir l'éditeur dans un nouvel onglet sur le site web CodeSandbox. CodeSandbox vous permet d'écrire du code dans votre navigateur et de prévisualiser ce que verront les utilisateurs de l'appli que vous aurez créée. Le nouvel onglet devrait afficher un carré vide et le code de démarrage pour ce tutoriel. @@ -261,19 +263,19 @@ body { -You can also follow this tutorial using your local development environment. To do this, you need to: +Vous pouvez aussi suivre ce tutoriel dans votre environnement de développement local. Pour cela, suivez ces étapes : -1. Install [Node.js](https://nodejs.org/en/) -1. In the CodeSandbox tab you opened earlier, press the top-left corner button to open the menu, and then choose **File > Export to ZIP** in that menu to download an archive of the files locally -1. Unzip the archive, then open a terminal and `cd` to the directory you unzipped -1. Install the dependencies with `npm install` -1. Run `npm start` to start a local server and follow the prompts to view the code running in a browser +1. Installez [Node.js](https://nodejs.org/fr/) +2. Dans l'onglet CodeSandbox ouvert plus tôt, appuyez sur le bouton en haut à gauche pour ouvrir le menu, puis choisissez **File › Export to ZIP** dans ce menu pour télécharger localement une archive des fichiers +3. Décompressez l'archive puis ouvre un terminal et `cd` dans le dossier que vous venez de décompresser +4. Installez les dépendances avec `npm install` +5. Lancer `npm start` pour démarrer un serveur local et suivez les invites pour voir le code s'exécuter dans le navigateur. -If you get stuck, don't let this stop you! Follow along online instead and try a local setup again later. +Si vous êtes bloqué·e, ne vous laissez pas décourager ! Suivez ce tutoriel en ligne et retentez une mise en place locale plus tard. -## Overview {/*overview*/} +## Survol {/*overview*/} Now that you're set up, let's get an overview of React! @@ -337,7 +339,7 @@ import './styles.css'; import App from './App'; ``` -Lines 1-5 brings all the necessary pieces together: +Lines 1-5 brings all the necessary pieces together: * React * React's library to talk to web browsers (React DOM) @@ -551,7 +553,7 @@ export default function Board() { } ``` -Note how unlike the browser `div`s, your own components `Board` and `Square` must start with a capital letter. +Note how unlike the browser `div`s, your own components `Board` and `Square` must start with a capital letter. Let's take a look: @@ -913,7 +915,7 @@ For local development, React DevTools is available as a [Chrome](https://chrome. -## Completing the game {/*completing-the-game*/} +## Finaliser le jeu {/*completing-the-game*/} By this point, you have all the basic building blocks for your tic-tac-toe game. To have a complete game, you now need to alternate placing "X"s and "O"s on the board, and you need a way to determine a winner. @@ -1094,7 +1096,7 @@ function Square({ value, onSquareClick }) { } ``` -Now you'll connect the `onSquareClick` prop to a function in the `Board` component that you'll name `handleClick`. To connect `onSquareClick` to `handleClick` you'll pass a function to the `onSquareClick` prop of the first `Square` component: +Now you'll connect the `onSquareClick` prop to a function in the `Board` component that you'll name `handleClick`. To connect `onSquareClick` to `handleClick` you'll pass a function to the `onSquareClick` prop of the first `Square` component: ```js {7} export default function Board() { @@ -1568,7 +1570,7 @@ function handleClick(i) { } ``` -To let the players know when the game is over, you can display text such as "Winner: X" or "Winner: O". To do that you'll add a `status` section to the `Board` component. The status will display the winner if the game is over and if the game is ongoing you'll display which player's turn is next: +To let the players know when the game is over, you can display text such as "Gagnant·e : X" or "Gagnant·e : O". To do that you'll add a `status` section to the `Board` component. The status will display the winner if the game is over and if the game is ongoing you'll display which player's turn is next: ```js {3-9,13} export default function Board() { @@ -1576,9 +1578,9 @@ export default function Board() { const winner = calculateWinner(squares); let status; if (winner) { - status = "Winner: " + winner; + status = "Gagnant·e : " + winner; } else { - status = "Next player: " + (xIsNext ? "X" : "O"); + status = "Prochain tour : " + (xIsNext ? "X" : "O"); } return ( @@ -1626,9 +1628,9 @@ export default function Board() { const winner = calculateWinner(squares); let status; if (winner) { - status = 'Winner: ' + winner; + status = 'Gagnant·e : ' + winner; } else { - status = 'Next player: ' + (xIsNext ? 'X' : 'O'); + status = 'Prochain tour : ' + (xIsNext ? 'X' : 'O'); } return ( @@ -1721,7 +1723,7 @@ body { -## Adding time travel {/*adding-time-travel*/} +## Voyager dans le temps {/*adding-time-travel*/} As a final exercise, let's make it possible to "go back in time" to the previous moves in the game. @@ -1900,9 +1902,9 @@ function Board({ xIsNext, squares, onPlay }) { const winner = calculateWinner(squares); let status; if (winner) { - status = 'Winner: ' + winner; + status = 'Gagnant·e : ' + winner; } else { - status = 'Next player: ' + (xIsNext ? 'X' : 'O'); + status = 'Prochain tour : ' + (xIsNext ? 'X' : 'O'); } return ( @@ -2049,9 +2051,9 @@ export default function Game() { const moves = history.map((squares, move) => { let description; if (move > 0) { - description = 'Go to move #' + move; + description = 'Aller au coup #' + move; } else { - description = 'Go to game start'; + description = 'Revenir au début'; } return (
  • @@ -2105,9 +2107,9 @@ function Board({ xIsNext, squares, onPlay }) { const winner = calculateWinner(squares); let status; if (winner) { - status = 'Winner: ' + winner; + status = 'Gagnant·e : ' + winner; } else { - status = 'Next player: ' + (xIsNext ? 'X' : 'O'); + status = 'Prochain tour : ' + (xIsNext ? 'X' : 'O'); } return ( @@ -2149,9 +2151,9 @@ export default function Game() { const moves = history.map((squares, move) => { let description; if (move > 0) { - description = 'Go to move #' + move; + description = 'Aller au coup #' + move; } else { - description = 'Go to game start'; + description = 'Revenir au début'; } return (
  • @@ -2333,9 +2335,9 @@ function Board({ xIsNext, squares, onPlay }) { const winner = calculateWinner(squares); let status; if (winner) { - status = 'Winner: ' + winner; + status = 'Gagnant·e : ' + winner; } else { - status = 'Next player: ' + (xIsNext ? 'X' : 'O'); + status = 'Prochain tour : ' + (xIsNext ? 'X' : 'O'); } return ( @@ -2377,9 +2379,9 @@ export default function Game() { const moves = history.map((squares, move) => { let description; if (move > 0) { - description = 'Go to move #' + move; + description = 'Aller au coup #' + move; } else { - description = 'Go to game start'; + description = 'Revenir au début'; } return (
  • @@ -2554,9 +2556,9 @@ function Board({ xIsNext, squares, onPlay }) { const winner = calculateWinner(squares); let status; if (winner) { - status = 'Winner: ' + winner; + status = 'Gagnant·e : ' + winner; } else { - status = 'Next player: ' + (xIsNext ? 'X' : 'O'); + status = 'Prochain tour : ' + (xIsNext ? 'X' : 'O'); } return ( @@ -2602,9 +2604,9 @@ export default function Game() { const moves = history.map((squares, move) => { let description; if (move > 0) { - description = 'Go to move #' + move; + description = 'Aller au coup #' + move; } else { - description = 'Go to game start'; + description = 'Revenir au début'; } return (
  • @@ -2764,9 +2766,9 @@ function Board({ xIsNext, squares, onPlay }) { const winner = calculateWinner(squares); let status; if (winner) { - status = 'Winner: ' + winner; + status = 'Gagnant·e : ' + winner; } else { - status = 'Next player: ' + (xIsNext ? 'X' : 'O'); + status = 'Prochain tour : ' + (xIsNext ? 'X' : 'O'); } return ( @@ -2810,9 +2812,9 @@ export default function Game() { const moves = history.map((squares, move) => { let description; if (move > 0) { - description = 'Go to move #' + move; + description = 'Aller au coup #' + move; } else { - description = 'Go to game start'; + description = 'Revenir au début'; } return (
  • diff --git a/src/sidebarLearn.json b/src/sidebarLearn.json index 7d527e973..9d5b0b9e0 100644 --- a/src/sidebarLearn.json +++ b/src/sidebarLearn.json @@ -11,7 +11,7 @@ "path": "/learn", "routes": [ { - "title": "Tutorial: Tic-Tac-Toe", + "title": "Tutoriel : Tic-Tac-Toe", "path": "/learn/tutorial-tic-tac-toe" }, { From 166a33173b047b26320261813f6e4eb19fa4c628 Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Wed, 26 Jul 2023 16:33:12 +0200 Subject: [PATCH 3/6] copy(tutorial): translate until Finalizing The Game --- src/content/learn/tutorial-tic-tac-toe.md | 160 +++++++++++----------- 1 file changed, 82 insertions(+), 78 deletions(-) diff --git a/src/content/learn/tutorial-tic-tac-toe.md b/src/content/learn/tutorial-tic-tac-toe.md index a9876ea0f..25f45c8d3 100644 --- a/src/content/learn/tutorial-tic-tac-toe.md +++ b/src/content/learn/tutorial-tic-tac-toe.md @@ -277,19 +277,19 @@ Si vous êtes bloqué·e, ne vous laissez pas décourager ! Suivez ce tutoriel ## Survol {/*overview*/} -Now that you're set up, let's get an overview of React! +À présent que vous êtes prêt·e, attaquons un survol de React ! -### Inspecting the starter code {/*inspecting-the-starter-code*/} +### Examiner le code de démarrage {/*inspecting-the-starter-code*/} -In CodeSandbox you'll see three main sections: +Dans CodeSandbox vous trouverez trois sections principales : -![CodeSandbox with starter code](../images/tutorial/react-starter-code-codesandbox.png) +![CodeSandbox avec le code de démarrage](../images/tutorial/react-starter-code-codesandbox.png) -1. The _Files_ section with a list of files like `App.js`, `index.js`, `styles.css` and a folder called `public` -1. The _code editor_ where you'll see the source code of your selected file -1. The _browser_ section where you'll see how the code you've written will be displayed +1. La section _Files_ contient une liste des fichiers tels que `App.js`, `index.js`, `styles.css` et un dossier nommé `public` +2. Le _code editor_ affiche le code source du fichier sélectionné +3. Le _browser_ affiche le résultat du code que vous avez écrit -The `App.js` file should be selected in the _Files_ section. The contents of that file in the _code editor_ should be: +Le fichier `App.js` devrait être sélectionné dans la section _Files_. Le contenu de ce fichier dans le _code editor_ devrait être le suivant : ```jsx export default function Square() { @@ -297,15 +297,15 @@ export default function Square() { } ``` -The _browser_ section should be displaying a square with a X in it like this: +La section _browser_ devrait afficher un carré avec un X à l'intérieur, comme ceci : -![x-filled square](../images/tutorial/x-filled-square.png) +![Carré avec un X à l’intérieur](../images/tutorial/x-filled-square.png) -Now let's have a look at the files in the starter code. +Jetons maintenant un coup d'œil au code de démarrage. #### `App.js` {/*appjs*/} -The code in `App.js` creates a _component_. In React, a component is a piece of reusable code that represents a part of a user interface. Components are used to render, manage, and update the UI elements in your application. Let's look at the component line by line to see what's going on: +Le code dans `App.js` crée un _composant_. Dans React, un composant est un bout de code réutilisable qui représente une partie de l'interface utilisateur (UI). Les composants sont utilisés pour afficher, gérer et mettre à jour des éléments d'UI dans votre application. Examinons ce composant ligne par ligne pour voir ce qui s'y passe : ```js {1} export default function Square() { @@ -313,7 +313,7 @@ export default function Square() { } ``` -The first line defines a function called `Square`. The `export` JavaScript keyword makes this function accessible outside of this file. The `default` keyword tells other files using your code that it's the main function in your file. +La première ligne définit une fonction appelée `Square`. Le mot-clé JavaScript `export` rend cette fonction accessible à l'extérieur de ce fichier. Le mot-clé `default` indique aux autres fichiers utilisant votre code qu'il s'agit là de la fonction principale de votre fichier. ```js {2} export default function Square() { @@ -321,15 +321,15 @@ export default function Square() { } ``` -The second line returns a button. The `return` JavaScript keyword means whatever comes after is returned as a value to the caller of the function. `` closes the JSX element to indicate that any following content shouldn't be placed inside the button. +La deuxième ligne renvoie un bouton. Le mot-clé JavaScript `return` indique que tout ce qui le suit est renvoyé comme valeur à l'appelant de la fonction. `` ferme l'élément JSX en indiquant que tout ce qui suit ne devrait pas figurer dans le bouton. #### `styles.css` {/*stylescss*/} -Click on the file labeled `styles.css` in the _Files_ section of CodeSandbox. This file defines the styles for your React app. The first two _CSS selectors_ (`*` and `body`) define the style of large parts of your app while the `.square` selector defines the style of any component where the `className` property is set to `square`. In your code, that would match the button from your Square component in the `App.js` file. +Cliquez sur le fichier nommé `styles.css` dans la section _Files_ de CodeSandbox. Ce fichier définit les styles de votre appli React. Les deux premiers _sélecteurs CSS_ (`*` et `body`) définissent le style de larges pans de votre appli, tandis que le sélecteur `.square` définit le style de tout composant dont la propriété `className` sera définie à `square`. Dans votre code, ça correspondrait au bouton de votre composant `Square` dans le fichier `App.js`. #### `index.js` {/*indexjs*/} -Click on the file labeled `index.js` in the _Files_ section of CodeSandbox. You won't be editing this file during the tutorial but it is the bridge between the component you created in the `App.js` file and the web browser. +Cliquez sur le fichier nommé `index.js` dans la section _Files_ de CodeSandbox. Vous ne modifierez pas ce fichier pendant ce tutoriel, mais il est la passerelle entre le composant que vous avez créé dans le fichier `App.js` et le navigateur web. ```jsx import { StrictMode } from 'react'; @@ -339,20 +339,20 @@ import './styles.css'; import App from './App'; ``` -Lines 1-5 brings all the necessary pieces together: +Les lignes 1 à 5 rassemblent toutes les pièces du puzzle : * React -* React's library to talk to web browsers (React DOM) -* the styles for your components -* the component you created in `App.js`. +* La bibliothèque React qui parle aux navigateurs web (React DOM) +* Les styles de vos composants +* Le composant que vous avez créé dans `App.js`. -The remainder of the file brings all the pieces together and injects the final product into `index.html` in the `public` folder. +Le reste du fichier connecte tout ça et injecte le résultat final dans `index.html` au sein du dossier `public`. -### Building the board {/*building-the-board*/} +### Construire le plateau de jeu {/*building-the-board*/} -Let's get back to `App.js`. This is where you'll spend the rest of the tutorial. +Revenons à `App.js`. C'est là que vous passerez le reste de ce tutoriel. -Currently the board is only a single square, but you need nine! If you just try and copy paste your square to make two squares like this: +À ce stade, le plateau n'est constitué que d'une seule case, mais il vous en faut neuf ! Si vous vous contentez de copier-coller votre carré pour en faire deux, comme ceci : ```js {2} export default function Square() { @@ -360,7 +360,7 @@ export default function Square() { } ``` -You'll get this error: +…vous obtiendrez cette erreur : @@ -368,7 +368,9 @@ You'll get this error: -React components need to return a single JSX element and not multiple adjacent JSX elements like two buttons. To fix this you can use *fragments* (`<>` and ``) to wrap multiple adjacent JSX elements like this: +*(« Des éléments JSX adjacents doivent être enrobés par une balise englobante. Vouliez-vous utiliser un Fragment JSX `<>...` ? », NdT.)* + +Les composants React doivent ne renvoyer qu'un unique élément JSX, et non plusieurs éléments JSX adjacents, comme nos deux boutons. Pour corriger ça, vous pouvez utiliser des *Fragments* (`<>` et ``) pour enrober plusieurs éléments JSX adjacents, comme ceci : ```js {3-6} export default function Square() { @@ -381,17 +383,17 @@ export default function Square() { } ``` -Now you should see: +Vous devriez maintenant voir ça : -![two x-filled squares](../images/tutorial/two-x-filled-squares.png) +![Deux carrés avec des X à l’intérieur](../images/tutorial/two-x-filled-squares.png) -Great! Now you just need to copy-paste a few times to add nine squares and... +Super ! Maintenant vous n'avez plus qu'à copier-coller davantage pour obtenir neuf carrés… -![nine x-filled squares in a line](../images/tutorial/nine-x-filled-squares.png) +![Neuf carrés sur une ligne, avec des X à l’intérieur](../images/tutorial/nine-x-filled-squares.png) -Oh no! The squares are all in a single line, not in a grid like you need for our board. To fix this you'll need to group your squares into rows with `div`s and add some CSS classes. While you're at it, you'll give each square a number to make sure you know where each square is displayed. +Disgrâce ! Les carrés sont tous sur la même ligne, au lieu de former une grille comme nous en avons besoin pour notre plateau. Pour corriger ça, vous allez devoir grouper vos carrés en ligne avec des `div` et ajouter quelques classes CSS. Tant que vous y êtes, donnez un numéro à chaque carré pour être sûr·e que vous savez où chaque carré est affiché. -In the `App.js` file, update the `Square` component to look like this: +Dans le fichier `App.js`, mettez à jour votre composant `Square` pour ressembler à ceci : ```js {3-19} export default function Square() { @@ -417,11 +419,11 @@ export default function Square() { } ``` -The CSS defined in `styles.css` styles the divs with the `className` of `board-row`. Now that you've grouped your components into rows with the styled `div`s you have your tic-tac-toe board: +Le CSS défini dans `styles.css` style les `div` dotés de la `className` de valeur `board-row`. À présent que vous avez groupé vos composants en ligne avec ces `div` mis en page, vous avez votre plateau de tic-tac-toe : -![tic-tac-toe board filled with numbers 1 through 9](../images/tutorial/number-filled-board.png) +![plateau de tic-tac-toe rempli par les numéros 1 à 9](../images/tutorial/number-filled-board.png) -But you now have a problem. Your component named `Square`, really isn't a square anymore. Let's fix that by changing the name to `Board`: +Mais nous avons un problème. Votre composant nommé `Square` n'est plus vraiment un carré tout seul. Corrigeons ça en changeant son nom pour `Board` : ```js {1} export default function Board() { @@ -429,7 +431,7 @@ export default function Board() { } ``` -At this point your code should look something like this: +À ce stade, votre code devrait ressembler à ceci : @@ -506,15 +508,15 @@ body { -Psssst... That's a lot to type! It's okay to copy and paste code from this page. However, if you're up for a little challenge, we recommend only copying code that you've manually typed at least once yourself. +Psssst… Ça fait un paquet de saisie de code ! N'hésitez pas à copier-coller le code de cette page. Ceci dit, si vous vous en sentez la force, nous vous conseillons de ne copier que le code que vous avez déjà tapé manuellement au moins une fois vous-même. -### Passing data through props {/*passing-data-through-props*/} +### Fournir des données avec les props {/*passing-data-through-props*/} -Next, you'll want to change the value of a square from empty to "X" when the user clicks on the square. With how you've built the board so far you would need to copy-paste the code that updates the square nine times (once for each square you have)! Instead of copy-pasting, React's component architecture allows you to create a reusable component to avoid messy, duplicated code. +Pour l'étape suivante, vous allez vouloir changer la valeur d'un carré de vide à « X » lorsque l'utilisateur clique sur le carré. Vu comme vous avez construit votre tableau jusqu'ici, il vous faudrait copier-coller le code qui met à jour un carré neuf fois (une fois par carré) ! Plutôt que de le copier-coller, l'architecture de composants de React vous permet de créer un composant réutilisable pour éviter du code dupliqué mal fichu. -First, you are going to copy the line defining your first square (``) from your `Board` component into a new `Square` component: +Pour commencez, copiez la ligne qui définit votre premier carré (``) depuis votre composant `Board` vers un nouveau composant `Square` : ```js {1-3} function Square() { @@ -526,7 +528,7 @@ export default function Board() { } ``` -Then you'll update the Board component to render that `Square` component using JSX syntax: +Ensuite, mettez à jour le composant `Board pour afficher un composant `Square` grâce à la syntaxe JSX : ```js {5-19} // ... @@ -553,15 +555,15 @@ export default function Board() { } ``` -Note how unlike the browser `div`s, your own components `Board` and `Square` must start with a capital letter. +Remarquez que contrairement aux `div` du navigateur, vos propres composants `Board` et `Square` doivent avoir un nom qui démarre par une lettre majuscule. -Let's take a look: +Voyons un peu le résultat : -![one-filled board](../images/tutorial/board-filled-with-ones.png) +![Un plateau rempli de chiffres un](../images/tutorial/board-filled-with-ones.png) -Oh no! You lost the numbered squares you had before. Now each square says "1". To fix this, you will use *props* to pass the value each square should have from the parent component (`Board`) to its child (`Square`). +Palsambleu ! Vous avez perdu les carrés numérotés que vous aviez jusque-là. À présent chaque carré dit « 1 ». Pour corriger ça, vous allez utiliser des *props* pour passer la valeur que chaque carré devrait avoir depuis le composant parent (`Board`) vers les enfants (`Square`). -Update the `Square` component to read the `value` prop that you'll pass from the `Board`: +Mettez à jour le composant `Square` pour lire une prop `value` que vous passerez depuis le `Board` : ```js {1} function Square({ value }) { @@ -569,9 +571,9 @@ function Square({ value }) { } ``` -`function Square({ value })` indicates the Square component can be passed a prop called `value`. +`function Square({ value })` indique que le composant `Square` peut recevoir une prop nommée `value`. -Now you want to display that `value` instead of `1` inside every square. Try doing it like this: +Utilisez maintenant la `value` plutôt que `1` dans l'affichage de chaque carré. Essayez comme ceci : ```js {2} function Square({ value }) { @@ -579,11 +581,11 @@ function Square({ value }) { } ``` -Oops, this is not what you wanted: +Zut, ça ne marche pas : -![value-filled board](../images/tutorial/board-filled-with-value.png) +![Un plateau rempli de « value »](../images/tutorial/board-filled-with-value.png) -You wanted to render the JavaScript variable called `value` from your component, not the word "value". To "escape into JavaScript" from JSX, you need curly braces. Add curly braces around `value` in JSX like so: +Vous vouliez afficher le contenu de la variable JavaScript nommée `value` au sein de votre composant, pas le mot “value”. Afin de « vous échapper vers JavaScript » depuis JSX, vous avez besoin d'accolades. Ajoutez des accolades autour de `value` dans votre JSX, comme ceci : ```js {2} function Square({ value }) { @@ -591,11 +593,11 @@ function Square({ value }) { } ``` -For now, you should see an empty board: +Pour le moment, vous devriez voir un plateau vide : -![empty board](../images/tutorial/empty-board.png) +![Un plateau vide](../images/tutorial/empty-board.png) -This is because the `Board` component hasn't passed the `value` prop to each `Square` component it renders yet. To fix it you'll add the `value` prop to each `Square` component rendered by the `Board` component: +C'est parce que le composant `Board` ne passe pas encore de prop `value` à chaque composant `Square` qu'il affiche. Corrigez ça en ajoutant une prop `value` à chaque composant `Square` affiché par le composant `Board` : ```js {5-7,10-12,15-17} export default function Board() { @@ -621,11 +623,11 @@ export default function Board() { } ``` -Now you should see a grid of numbers again: +Vous devriez retrouver votre grille numérotée : -![tic-tac-toe board filled with numbers 1 through 9](../images/tutorial/number-filled-board.png) +![Un plateau de tic-tac-toe rempli des nombres 1 à 9](../images/tutorial/number-filled-board.png) -Your updated code should look like this: +Votre code à jour devrait ressembler à ceci : @@ -704,14 +706,16 @@ body { -### Making an interactive component {/*making-an-interactive-component*/} +### Rendre le composant interactif {/*making-an-interactive-component*/} + +Faisons en sorte le composant `Square` se remplisse d'un `X` lorsqu'on clique dessus. -Let's fill the `Square` component with an `X` when you click it. Declare a function called `handleClick` inside of the `Square`. Then, add `onClick` to the props of the button JSX element returned from the `Square`: +Déclarez une fonction appelée `handleClick` au sein du composant `Square`. Ensuite, ajoutez la prop `onClick` à l'élément JSX de bouton renvoyé par `Square` : ```js {2-4,9} function Square({ value }) { function handleClick() { - console.log('clicked!'); + console.log('cliqué !'); } return ( @@ -725,19 +729,19 @@ function Square({ value }) { } ``` -If you click on a square now, you should see a log saying `"clicked!"` in the _Console_ tab at the bottom of the _Browser_ section in CodeSandbox. Clicking the square more than once will log `"clicked!"` again. Repeated console logs with the same message will not create more lines in the console. Instead, you will see an incrementing counter next to your first `"clicked!"` log. +Si vous cliquez sur un carré désomrais, vous devriez voir un message disant `"cliqué !"` dans l'onglet _Console_ en bas de la section _Browser_ de CodeSandbox. Des clics supplémentaires devraient à nouveau y afficher `"cliqué !"`. Des logs multiples du même message n'ajouteront pas des lignes dans la console : vous verrez plutôt un compteur s'incrémenter à côté du premier message `"cliqué !"`. -If you are following this tutorial using your local development environment, you need to open your browser's Console. For example, if you use the Chrome browser, you can view the Console with the keyboard shortcut **Shift + Ctrl + J** (on Windows/Linux) or **Option + ⌘ + J** (on macOS). +Si vous suivez ce tutoriel dans votre environnement de développement local, vous aurez besoin d'ouvrir la console de votre navigateur. Par exemple, si vous utilisez un navigateur basé Chromium tel que Chrome, Edge ou Brave, vous pouvez ouvrir la console avec le raccourci clavier Maj + Ctrl + J** (sur Windows/Linux) ou **Option + ⌘ + J** (sur macOS). -As a next step, you want the Square component to "remember" that it got clicked, and fill it with an "X" mark. To "remember" things, components use *state*. +Vous souhaitez maintenant que le composant `Square` « se souvienne » qu'on lui a cliqué dessus, et se remplisse alors avec la marque « X ». Pour « se souvenir » de choses, les composants utilisent *l'état*. -React provides a special function called `useState` that you can call from your component to let it "remember" things. Let's store the current value of the `Square` in state, and change it when the `Square` is clicked. +React fournit une fonction spéciale appelée `useState` que vous pouvez appeler depuis votre composant pour qu'il « se souvienne » de choses. Stockons donc la valeur actuelle de `Square` dans un état, et modifions-la quand on clique sur le `Square`. -Import `useState` at the top of the file. Remove the `value` prop from the `Square` component. Instead, add a new line at the start of the `Square` that calls `useState`. Have it return a state variable called `value`: +Importez `useState` au début du fichier. Retirez la prop `value` du composant `Square`. Remplacez-la par une nouvelle ligne au début de la fonction `Square` qui appelle `useState`. Faites-lui renvoyer une variable d'état appelée `value` : ```js {1,3,4} import { useState } from 'react'; @@ -749,9 +753,9 @@ function Square() { //... ``` -`value` stores the value and `setValue` is a function that can be used to change the value. The `null` passed to `useState` is used as the initial value for this state variable, so `value` here starts off equal to `null`. +`value` stocke la valeur et `setValue` est une fonction qu'on peut utiliser pour modifier la valeur. Le `null` passé à `useState` est utilisé comme valeur initiale de la variable d'état, de sorte que `value` démarre ici à `null`. -Since the `Square` component no longer accepts props anymore, you'll remove the `value` prop from all nine of the Square components created by the Board component: +Puis le composant `Square` n'accepte plus de props, vous pouvez retirer les props `value` des neuf composants `Square` créés dans le composant `Board` : ```js {6-8,11-13,16-18} // ... @@ -778,7 +782,7 @@ export default function Board() { } ``` -Now you'll change `Square` to display an "X" when clicked. Replace the `console.log("clicked!");` event handler with `setValue('X');`. Now your `Square` component looks like this: +Modifiez maintenant `Square` pour afficher un « X » quand on clique dessus. Remplacez le `console.log("cliqué !");` du gestionnaire d'événement par `setValue('X');`. À présent votre composant `Square` devrait ressembler à ceci : ```js {5} function Square() { @@ -799,13 +803,13 @@ function Square() { } ``` -By calling this `set` function from an `onClick` handler, you're telling React to re-render that `Square` whenever its `` ferme l'élément JSX en indiquant que tout ce qui suit ne devrait pas figurer dans le bouton. +La deuxième ligne renvoie un bouton. Le mot-clé JavaScript `return` indique que tout ce qui le suit est renvoyé comme valeur à l'appelant de la fonction. `` ferme l'élément JSX en indiquant que tout ce qui suit ne devrait pas figurer dans le bouton. #### `styles.css` {/*stylescss*/} -Cliquez sur le fichier nommé `styles.css` dans la section _Files_ de CodeSandbox. Ce fichier définit les styles de votre appli React. Les deux premiers _sélecteurs CSS_ (`*` et `body`) définissent le style de larges pans de votre appli, tandis que le sélecteur `.square` définit le style de tout composant dont la propriété `className` sera définie à `square`. Dans votre code, ça correspondrait au bouton de votre composant `Square` dans le fichier `App.js`. +Cliquez sur le fichier nommé `styles.css` dans la section _Files_ de CodeSandbox. Ce fichier définit les styles de votre appli React. Les deux premiers _sélecteurs CSS_ (`*` et `body`) définissent le style de larges pans de votre appli, tandis que le sélecteur `.square` définit le style de tout composant dont la propriété `className` vaudra `square`. Dans votre code, ça correspondrait au bouton de votre composant `Square` dans le fichier `App.js`. #### `index.js` {/*indexjs*/} @@ -516,7 +516,7 @@ Psssst… Ça fait un paquet de saisie de code ! N'hésitez pas à copier-colle Pour l'étape suivante, vous allez vouloir changer la valeur d'un carré de vide à « X » lorsque l'utilisateur clique sur le carré. Vu comme vous avez construit votre tableau jusqu'ici, il vous faudrait copier-coller le code qui met à jour un carré neuf fois (une fois par carré) ! Plutôt que de le copier-coller, l'architecture de composants de React vous permet de créer un composant réutilisable pour éviter du code dupliqué mal fichu. -Pour commencez, copiez la ligne qui définit votre premier carré (``) depuis votre composant `Board` vers un nouveau composant `Square` : +Pour commencer, copiez la ligne qui définit votre premier carré (``) depuis votre composant `Board` vers un nouveau composant `Square` : ```js {1-3} function Square() { @@ -528,7 +528,7 @@ export default function Board() { } ``` -Ensuite, mettez à jour le composant `Board pour afficher un composant `Square` grâce à la syntaxe JSX : +Ensuite, mettez à jour le composant `Board` pour afficher un composant `Square` grâce à la syntaxe JSX : ```js {5-19} // ... @@ -597,7 +597,7 @@ Pour le moment, vous devriez voir un plateau vide : ![Un plateau vide](../images/tutorial/empty-board.png) -C'est parce que le composant `Board` ne passe pas encore de prop `value` à chaque composant `Square` qu'il affiche. Corrigez ça en ajoutant une prop `value` à chaque composant `Square` affiché par le composant `Board` : +C'est parce que le composant `Board` ne passe pas encore de prop `value` à chaque composant `Square` qu'il affiche. Corrigez ça en ajoutant une prop `value` adaptée pour chaque composant `Square` affichée par le composant `Board` : ```js {5-7,10-12,15-17} export default function Board() { @@ -708,7 +708,7 @@ body { ### Rendre le composant interactif {/*making-an-interactive-component*/} -Faisons en sorte le composant `Square` se remplisse d'un `X` lorsqu'on clique dessus. +Faisons en sorte que le composant `Square` se remplisse d'un `X` lorsqu'on clique dessus. Déclarez une fonction appelée `handleClick` au sein du composant `Square`. Ensuite, ajoutez la prop `onClick` à l'élément JSX de bouton renvoyé par `Square` : @@ -729,11 +729,11 @@ function Square({ value }) { } ``` -Si vous cliquez sur un carré désomrais, vous devriez voir un message disant `"cliqué !"` dans l'onglet _Console_ en bas de la section _Browser_ de CodeSandbox. Des clics supplémentaires devraient à nouveau y afficher `"cliqué !"`. Des logs multiples du même message n'ajouteront pas des lignes dans la console : vous verrez plutôt un compteur s'incrémenter à côté du premier message `"cliqué !"`. + Désormais, si vous cliquez sur un carré, vous devriez voir un message disant `"cliqué !"` dans l'onglet _Console_ en bas de la section _Browser_ de CodeSandbox. Des clics supplémentaires devraient à nouveau y afficher `"cliqué !"`. Des logs multiples du même message n'ajouteront pas de lignes dans la console : vous verrez plutôt un compteur s'incrémenter à côté du premier message `"cliqué !"`. -Si vous suivez ce tutoriel dans votre environnement de développement local, vous aurez besoin d'ouvrir la console de votre navigateur. Par exemple, si vous utilisez un navigateur basé Chromium tel que Chrome, Edge ou Brave, vous pouvez ouvrir la console avec le raccourci clavier Maj + Ctrl + J** (sur Windows/Linux) ou **Option + ⌘ + J** (sur macOS). +Si vous suivez ce tutoriel dans votre environnement de développement local, vous aurez besoin d'ouvrir la console de votre navigateur. Par exemple, si vous utilisez un navigateur basé Chromium tel que Chrome, Edge ou Brave, vous pouvez ouvrir la console avec le raccourci clavier **Maj + Ctrl + J** (sur Windows/Linux) ou **Option + ⌘ + J** (sur macOS). @@ -755,7 +755,7 @@ function Square() { `value` stocke la valeur et `setValue` est une fonction qu'on peut utiliser pour modifier la valeur. Le `null` passé à `useState` est utilisé comme valeur initiale de la variable d'état, de sorte que `value` démarre ici à `null`. -Puis le composant `Square` n'accepte plus de props, vous pouvez retirer les props `value` des neuf composants `Square` créés dans le composant `Board` : +Puisque le composant `Square` n'accepte plus de props, vous pouvez retirer les props `value` des neuf composants `Square` créés dans le composant `Board` : ```js {6-8,11-13,16-18} // ... @@ -809,7 +809,7 @@ En appelant la fonction `set` depuis un gestionnaire `onClick`, vous demandez à Chaque `Square` a son propre état : la `value` stockée par chaque `Square` est totalement indépendante des autres. Lorsque vous appelez la fonction `set` dans un composant, React met automatiquement à jour ses composants enfants aussi. -Après que vous aurez fait les modifications ci-dessus, votre code derait ressembler à ceci : +Après que vous aurez fait les modifications ci-dessus, votre code devrait ressembler à ceci : @@ -915,23 +915,23 @@ Pour examiner un composant spécifique à l'écran, utilisez le bouton en haut -Pour le développement local, les outils de développeemnt React sont disponibles sous forme d'extension navigateur pour [Chrome](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en), [Firefox](https://addons.mozilla.org/en-US/firefox/addon/react-devtools/) et [Edge](https://microsoftedge.microsoft.com/addons/detail/react-developer-tools/gpphkfbcpidddadnkolkpfckpihlkkil). Installez-les, après quoi l'onglet *Composants* apparaîtra dans les outils de développement de votre navigateur sur les sites utilisant React. +Pour le développement local, les outils de développement React sont disponibles sous forme d'extension navigateur pour [Chrome](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en), [Firefox](https://addons.mozilla.org/en-US/firefox/addon/react-devtools/) et [Edge](https://microsoftedge.microsoft.com/addons/detail/react-developer-tools/gpphkfbcpidddadnkolkpfckpihlkkil). Installez-les, après quoi l'onglet *Composants* apparaîtra dans les outils de développement de votre navigateur sur les sites utilisant React. ## Finaliser le jeu {/*completing-the-game*/} -À ce stade, vous avez toutes les briques élémentaires de votre jeu de tic-tac-toe. Pour finaliser le jeu, vous devez placer des « X » et des « O » en alternance sur le plateau, et devez pouvoir déterminer qui gagne (et quand). +À ce stade, vous avez toutes les briques élémentaires de votre jeu de tic-tac-toe. Pour finaliser le développement du jeu, vous devez placer des « X » et des « O » en alternance sur le plateau, et devez pouvoir déterminer qui gagne (et quand). ### Faire remonter l'état {/*lifting-state-up*/} -Actuellement, chaque composant `Square` maintient une partie de l'état du jeu. Pour déterminer si quelqu'un a gagné la partie de tic-tac-toe, le `Board` doit se débrouiller pour connaître l'état de chacun des 9 composants `Square`. +Actuellement, chaque composant `Square` maintient une partie de l'état du jeu. Pour déterminer si quelqu'un a gagné la partie de tic-tac-toe, le `Board` doit donc se débrouiller pour connaître l'état de chacun des 9 composants `Square`. Comment vous y prendriez-vous ? Vous pourriez d'abord penser que le `Board` a besoin de « demander » à chaque `Square` quel est son état interne. Même si une telle approche est techniquement possible en React, nous la déconseillons car elle engendre du code difficile à comprendre, difficile à remanier et fortement sujet aux bugs. La meilleure approche consiste plutôt à stocker l'état du jeu dans le composant parent `Board`, plutôt qu'éparpillé dans chaque `Square`. Le composant `Board` peut dire à chaque `Square` quoi afficher en lui passant une prop, comme vous l'aviez fait en passant un nombre à chaque `Square`. **Pour récupérer des données depuis de multiples enfants, ou pour que deux composants enfants communiquent l'un avec l'autre, déclarez plutôt leur état partagé dans leur composant parent. Le composant parent peut transmettre cet état à ses enfants *via* les props. Ça permet de garder les enfants synchronisés entre eux, ainsi qu'avec leur parent.** -Faire remonter l'état dans un composant parent est une pratique courante lorsque des composants React sont remaniés. +Faire remonter l'état dans un composant parent est une pratique courante lors de la refonte du code des composants React. Tirons parti de cette opportunité pour essayer ça. Modifiez le composant `Board` pour qu'il déclare une variable d'état nommée `squares` qui contient par défaut un tableau de 9 `null` correspondant aux neuf cases : @@ -945,7 +945,7 @@ export default function Board() { } ``` -`Array(9).fill(null)` crée un tableau de neuf éléments puis les définit tous à `null`. L'appel `useState()` qui l'enrobe déclare une variable d'état `squares` qui vaut initialement ce tableau. Chaque entrée du tableau correspond à la valeur d'une case. Lorsque vous remplirez le plateau par la suite, le tableau ressemblera plus à ceci : +`Array(9).fill(null)` crée un tableau de neuf éléments puis les définit tous à `null`. L'appel `useState()` qui l'enrobe déclare une variable d'état `squares` qui vaut initialement ce tableau. Chaque entrée du tableau correspond à la valeur d'une case. Lorsque vous remplirez le plateau par la suite, le tableau aura une valeur ressemblant davantage à ceci : ```jsx ['O', null, 'X', 'X', 'X', 'O', 'O', null, null] @@ -978,7 +978,7 @@ export default function Board() { } ``` -Modifiez ensuite le composant `Square` pour qu'il reçoive cette prop depuis le composant `Board . Il faudra donc retirer du composant `Square` sa gestion d'état interne pour `value` ainsi que la prop `onClick` du bouton : +Modifiez ensuite le composant `Square` pour qu'il reçoive cette prop depuis le composant `Board`. Il faudra donc retirer du composant `Square` sa gestion d'état interne pour `value` ainsi que la prop `onClick` du bouton : ```js {1,2} function Square({value}) { @@ -1143,7 +1143,7 @@ JavaScript utilise des [fermetures lexicales](https://developer.mozilla.org/docs -Vous pouvez désormais ajouter des X au plateau… mais seulement dans la case en haut à gauche. Votre fonction `handleClick` indexe en dur cette case (`0`). Mettons `handleClick` à jour pour pouvoir modifier n'importe quelle case. Ajoutez un paramètre `i` à la fonction `handleClick` qui prendra l'index de la case à modifier : +Vous pouvez désormais ajouter des X au plateau… mais seulement dans la case en haut à gauche. Votre fonction `handleClick` indexe en dur cette case (`0`). Mettons `handleClick` à jour pour pouvoir modifier n'importe quelle case. Ajoutez un paramètre `i` à la fonction `handleClick`, destiné à recevoir l'index de la case du plateau à modifier : ```js {4,6} export default function Board() { @@ -1167,7 +1167,7 @@ Ensuite, vous allez devoir passer ce `i` à `handleClick`. Vous pourriez essaye ``` -Voici pourquoi ça ne marche pas : l'appel `handleClick(0)` fera partie du rendu du composant plateau. Puisque `handleClick(0)` altère l'état du plateau en appelant `setSquares`, votre composant plateau tout entier va refaire un rendu. Mais celui-ci appellera à nouveau `handleClick(0)`, ce qui revient à une boucle infinie : +Voici pourquoi ça ne marchera pas : l'appel `handleClick(0)` fera partie du rendu du composant plateau. Puisque `handleClick(0)` altère l'état du plateau en appelant `setSquares`, votre composant plateau tout entier va refaire un rendu. Mais celui-ci appellera à nouveau `handleClick(0)`, ce qui revient à une boucle infinie : @@ -1183,7 +1183,7 @@ Lorsque vous passiez `onSquareClick={handleClick}`, vous passiez la fonction `ha Vous pourriez corriger ça en créant une fonction `handleFirstSquareClick` qui appelle `handleClick(0)`, une fonction `handleSecondSquareClick` qui appelle `handleClick(1)`, et ainsi de suite. Vous passeriez (plutôt qu'appeler) ces fonctions comme props, du genre `onSquareClick={handleFirstSquareClick}`. Ça règlerait le souci de boucle infinie. -Ceci dit, définir neuf fonctions distinctes avec des noms dédiés, c'est plutôt verbeux… Faisons plutôt comme ceci : +Ceci dit, définir neuf fonctions distinctes avec des noms dédiés, c'est verbeux… Faisons plutôt comme ceci : ```js {6} export default function Board() { @@ -1327,17 +1327,17 @@ body { À présent que votre gestion d'état est dans le composant `Board`, le composant parent `Board` passe les props aux composants enfants `Square` de façon à ce qu'ils soient affichés correctement. Lorsque vous cliquez sur un `Square`, le composant enfant `Square` demande désormais au composant parent `Board` de mettre à jour l'état du plateau. Lorsque l'état de `Board` change, aussi bien le composant `Board` que tous les enfants `Square` refont leur rendu automatiquement. Conserver l'état de toutes les cases dans le composant `Board` nous permettra plus tard de déterminer qui gagne. -Récapitulons ce qui se passe lorsque l'utilisateur clique sur la cause supérieure gauche du plateau pour y ajouter un `X` : +Récapitulons ce qui se passe techniquement lorsque l'utilisateur clique sur la case supérieure gauche du plateau pour y ajouter un `X` : 1. Le clic sur la case supérieure gauche exécute la fonction que le `button` a reçu dans sa prop `onClick` depuis le composant `Square`. Ce composant `Square` a reçu cette fonction dans sa prop `onSquareClick`, fournie par `Board`. Le composant `Board` a défini cette fonction directement dans son JSX. Elle appelle `handleClick` avec un argument à `0`. -2. `handleClick` utilise son argument (`0`) pour mettre à jour le premier élément du tableau `suqares` de `null` à `X`. +2. `handleClick` utilise son argument (`0`) pour mettre à jour le premier élément du tableau `squares`, le faisant passer de `null` à `X`. 3. L'état `squares` du composant `Board` est mis à jour, du coup `Board` et tous ses enfants refont leur rendu. Ça modifie la prop `value` du composant `Square` d'index `0` pour la passer de `null` à `X`. -Au final l'utilisateur voit que la case supérieure gauche a changé, passant du vide à un `X`, après qu'il a cliqué dessus. +Au final l'utilisateur voit que la case supérieure gauche a changé après qu'il a cliqué dessus : elle est passée du vide à un `X`. -L'attribut `onClick` de l'élément DOM `
  • ``` -Quand votre liste est ré-affichée, Reaxct prend la clé de chaque élément de liste et recherche l'élément de la liste précédente avec la même clé. S'il ne le trouve pas, Reaxt crée un composant. Si la liste à jour n'a pas une clé qui existait auparavant, React détruit l'ancien composant correspondant. Si deux clés correspondent, le composant correspondant est déplacé si besoin. +Quand votre liste est ré-affichée, React prend la clé de chaque élément de liste et recherche l'élément de la liste précédente avec la même clé. S'il ne le trouve pas, React crée un composant. Si la liste à jour n'a pas une clé qui existait auparavant, React détruit l'ancien composant correspondant. Si deux clés correspondent, le composant correspondant est déplacé si besoin. Les clés informent React sur l'identité de chaque composant, ce qui lui permet de maintenir l'état d'un rendu à l'autre. Si la clé d'un composant change, il sera détruit puis recréé avec un état réinitialisé. -`key` est une propriété spéciale réservée par React. Lorsqu'un élément est créé, Reaxct extrait la propriété `key` et la stocke directement dans l'élément renvoyé. Même si `key` semble être passé comme une prop, React l'utilise automatiquement pour déterminer quel composant mettre à jour. Un composant n'a aucun moyen de demander la `key` que son parent a spécifié. +`key` est une propriété spéciale réservée par React. Lorsqu'un élément est créé, React extrait la propriété `key` et la stocke directement dans l'élément renvoyé. Même si `key` semble être passé comme une prop, React l'utilise automatiquement pour déterminer quel composant mettre à jour. Un composant n'a aucun moyen de demander la `key` que son parent a spécifié. **Nous vous conseillons fortement d'affecter des clés appropriées dès que vous construisez des listes dynamiques.** Si vous n'en avez pas, envisagez de restructurer vos données pour qu'elles en comportent. -Si aucune clé n'est spécifié, React signalera une erreur et utiliser par défaut l'index dans le tableau comme clé. Recourir à l'index en tant que clé pose problème dès que vous essayez de réordonner la liste ou d'y insérer ou retirer des éléments. Passer explicitement `key={i}` réduit certes l'erreur au silence, mais ne résoud en rien le problème sous-jacent, c'est donc une approche généralement déconseillée. +Si aucune clé n'est spécifiée, React signalera une erreur et utilisera par défaut l'index dans le tableau comme clé. Recourir à l'index en tant que clé pose problème dès que vous essayez de réordonner la liste ou d'y insérer ou retirer des éléments. Passer explicitement `key={i}` réduit certes l'erreur au silence, mais ne résout en rien le problème sous-jacent, c'est donc une approche généralement déconseillée. Les clés n'ont pas besoin d'être uniques au global ; elles doivent juste être uniques au sein de la liste concernée. @@ -2478,7 +2478,7 @@ body {
    -Avant de pouvoir implémenter `jumpTo`, il faut que le composant `Game` déterminer le coup que l'utilisateur est en train de consulter. Ajoutez une variable d'état nommée `currentMove`, qui vaudra par défaut `0` : +Avant de pouvoir implémenter `jumpTo`, il faut que le composant `Game` détermine le coup que l'utilisateur est en train de consulter. Ajoutez une variable d'état nommée `currentMove`, qui vaudra par défaut `0` : ```js {4} export default function Game() { @@ -2506,7 +2506,7 @@ export default function Game() { Il faut maintenant apporter deux modifications à la fonction `handlePlay` de `Game`, appelée lorsqu'on clique sur une case. - Si vous « revenez en arrière » puis faites un nouveau coup à partir de ce point, vous voulez ne conserver l'historique que jusqu'à ce point. Au lieu d'ajouter ` nextSquares` après tous les éléments (avec la syntaxe de *spread* `...`) de `history`, vous voudrez l'ajouter après les éléments de `history.slice(0, currentMove + 1)`, pour ne garder que cette portion de l'historique d'origine. -- Chaque fois qu'un coup est joué, il faut mettre à jour `currentMove` pour pointer sur la dernière entrée d'historique. +- À chaque coup, il faut mettre à jour `currentMove` pour pointer sur la dernière entrée d'historique. ```js {2-4} function handlePlay(nextSquares) { @@ -2530,7 +2530,7 @@ export default function Game() { } ``` -Si vous cliquez sur n'importe quelle état de l'historique de la partie, le plateau de tic-tac-toe devrait immédiatement afficher l'état du plateau à cette étape-là. +Si vous cliquez sur n'importe quelle étape de l'historique de la partie, le plateau de tic-tac-toe devrait immédiatement afficher l'état du plateau à cette étape-là. @@ -2705,7 +2705,7 @@ body { Si vous observez attentivement le code, vous remarquerez peut-être que `xIsNext === true` quand `currentMove` est pair, et que `xIsNext === false` quand `currentMove` est impair. En d'autre termes, si vous connaissez la valeur de `currentMove`, vous pouvez toujours déduire celle de `xIsNext`. -Il n'y a dès lors aucune raison de stocker les deux informations dans l'état. En fait, vous devriez activement chercher à ne rien stocker de redondant dans l'état. Simplifier ce que vous y stocker réduit les bugs et facilite la compréhension de votre code. Modifiez `Game` de façon à ce qu'il ne stocke plus `xIsNext` comme une variable d'état distincte, mais le calcule plutôt sur base de `currentMove` : +Il n'y a dès lors aucune raison de stocker les deux informations dans l'état. En fait, vous devriez activement chercher à ne rien stocker de redondant dans l'état. Simplifier ce que vous y stockez réduit les bugs et facilite la compréhension de votre code. Modifiez `Game` de façon à ce qu'il ne stocke plus `xIsNext` comme une variable d'état distincte, mais le calcule plutôt sur base de `currentMove` : ```js {4,11,15} export default function Game() { @@ -2727,7 +2727,7 @@ export default function Game() { } ``` -Vous n'avez plus besoin de la déclaration de variable d'état `xIsNext`, ni d'appels à `setXIsNext`. Il n'est du coup plus posisble que `xIsNext` et `currentMove` se désynchronisent, même si vous faisiez une erreur en codant un des composants. +Vous n'avez plus besoin de la déclaration de variable d'état `xIsNext`, ni d'appels à `setXIsNext`. Il n'y a du coup plus aucun risque que `xIsNext` et `currentMove` se désynchronisent, même si vous faisiez une erreur en codant un des composants. ### En résumé {/*wrapping-up*/} @@ -2911,10 +2911,10 @@ body { Si vous avez un peu plus de temps ou souhaitez pratiquer vos compétences React toutes fraîches, voici quelques idées d'améliorations que vous pourriez apporter à ce jeu de tic-tac-toe, par ordre croissant de difficulté : -1. Pour la coup actuel uniquement, affichez « Vous êtes au coup #… » plutôt qu'un bouton. +1. Pour le coup actuel uniquement, affichez « Vous êtes au coup #… » plutôt qu'un bouton. 2. Remaniez `Board` pour qu'il utilise deux boucles au lieu de coder les rangées et cases du plateau en dur. 3. Ajoutez un bouton de bascule qui permet de trier les coups par ordre croissant (du premier au dernier) ou décroissant (du dernier au premier). -4. Lorsqu'un joueur gagne, mettez en exergue les trois cases qui ont déclenché sa victoire (et si personne ne gagne, affichez un message indiquant un match nul). +4. Lorsqu'un joueur gagne, mettez en exergue les trois cases qui constituent sa victoire (et si personne ne gagne, affichez un message indiquant un match nul). 5. Affichez l'emplacement de chaque coup (ligne, colonne) dans l'historique des coups joués. Au cours de ce tutoriel, vous avez abordé des concepts React tels que les éléments, les composants, les props et l'état. À présent que vous avez pu les voir en action dans le cadre de la construction de ce jeu, allez donc lire [Penser en React](/learn/thinking-in-react) pour explorer ces mêmes concepts dans le cadre de la construction de l'UI d'une appli.