diff --git a/src/content/learn/sharing-state-between-components.md b/src/content/learn/sharing-state-between-components.md index 149164fe1..e7c502af6 100644 --- a/src/content/learn/sharing-state-between-components.md +++ b/src/content/learn/sharing-state-between-components.md @@ -1,31 +1,31 @@ --- -title: Sharing State Between Components +title: Partager l'état entre des composants --- -Sometimes, you want the state of two components to always change together. To do it, remove state from both of them, move it to their closest common parent, and then pass it down to them via props. This is known as *lifting state up,* and it's one of the most common things you will do writing React code. +Vous souhaitez parfois que les états de deux composants changent toujours ensemble. Pour ça, retirez leurs états et fusionnez-les dans leur plus proche parent commun, puis passez-leur ces données *via* les props. C'est ce qu'on appelle *faire remonter l'état*, et c'est l'une des choses les plus communes que vous ferez en écrivant du code React. -- How to share state between components by lifting it up -- What are controlled and uncontrolled components +- Comment partager l'état entre composants en le faisant remonter +- Ce que sont les composants contrôlés et non contrôlés -## Lifting state up by example {/*lifting-state-up-by-example*/} +## Faire remonter l'état par l'exemple {/*lifting-state-up-by-example*/} -In this example, a parent `Accordion` component renders two separate `Panel`s: +Dans cet exemple, un composant parent `Accordion` affiche deux `Panel` distincts : * `Accordion` - `Panel` - `Panel` -Each `Panel` component has a boolean `isActive` state that determines whether its content is visible. +Chaque composant `Panel` a une variable d'état booléenne `isActive` qui définit si le contenu du panneau est visible ou non. -Press the Show button for both panels: +Appuyez sur le bouton Afficher pour les deux panneaux : @@ -41,7 +41,7 @@ function Panel({ title, children }) {

{children}

) : ( )} @@ -52,11 +52,12 @@ export default function Accordion() { return ( <>

Almaty, Kazakhstan

- + + Avec une population d'environ 2 millions d'habitants, Almaty est la plus grande ville du Kazakhstan. Elle en était la capitale 1929 à 1997. With a population of about 2 million, Almaty is Kazakhstan's largest city. From 1929 to 1997, it was its capital city. - - The name comes from алма, the Kazakh word for "apple" and is often translated as "full of apples". In fact, the region surrounding Almaty is thought to be the ancestral home of the apple, and the wild Malus sieversii is considered a likely candidate for the ancestor of the modern domestic apple. + + Le nom vient de алма, le mot kazakh pour « pomme » ; il est souvent traduit par « pleine de pommes ». En fait, la région entourant Almaty est considérée comme le berceau ancestral de la pomme, et la Malus sieversii sauvage est considérée comme une probable candidate pour être l'ancêtre de la pomme domestique moderne. ); @@ -73,59 +74,59 @@ h3, p { margin: 5px 0px; }
-Notice how pressing one panel's button does not affect the other panel--they are independent. +Constatez que le fait d'appuyer sur le bouton d'un des panneaux n'affecte pas l'affichage de l'autre panneau : ils sont indépendants. - + -Initially, each `Panel`'s `isActive` state is `false`, so they both appear collapsed +Initialement, l'état `isActive` de chaque `Panel` vaut `false`, ils apparaissent donc repliés. - + -Clicking either `Panel`'s button will only update that `Panel`'s `isActive` state alone +Le fait de cliquer sur le bouton d'un `Panel` ne met à jour que l'état `isActive` de ce `Panel`. -**But now let's say you want to change it so that only one panel is expanded at any given time.** With that design, expanding the second panel should collapse the first one. How would you do that? +**Supposons maintenant que vous souhaitiez le modifier afin qu'un seul panneau soit déplié à la fois.** Avec cette conception, étendre le second panneau devrait replier le premier. Comment feriez-vous ça ? -To coordinate these two panels, you need to "lift their state up" to a parent component in three steps: +Afin de coordonner ces deux panneaux, vous devez « faire remonter leur état » jusqu'à un composant parent en trois étapes : -1. **Remove** state from the child components. -2. **Pass** hardcoded data from the common parent. -3. **Add** state to the common parent and pass it down together with the event handlers. +1. **Retirez** les états des composants enfants. +2. **Passez** des valeurs codées en dur depuis le parent commun. +3. **Ajoutez** l'état au parent commun et passez-le aux enfants avec les gestionnaires d'événements. -This will allow the `Accordion` component to coordinate both `Panel`s and only expand one at a time. +Ça permettra au composant `Accordion` de coordonner les deux `Panel` et ainsi n'en déplier qu'un seul à la fois. -### Step 1: Remove state from the child components {/*step-1-remove-state-from-the-child-components*/} +### Étape 1 : retirez l'état des composants enfants {/*step-1-remove-state-from-the-child-components*/} -You will give control of the `Panel`'s `isActive` to its parent component. This means that the parent component will pass `isActive` to `Panel` as a prop instead. Start by **removing this line** from the `Panel` component: +Vous donnerez le contrôle du `isActive` des `Panel` au composant parent. Ça signifie que le composant parent passera `isActive` aux `Panel` *via* les props. Commencez par **supprimer cette ligne** du composant `Panel` : ```js const [isActive, setIsActive] = useState(false); ``` -And instead, add `isActive` to the `Panel`'s list of props: +À la place, ajoutez `isActive` à la liste des props de `Panel` : ```js function Panel({ title, children, isActive }) { ``` -Now the `Panel`'s parent component can *control* `isActive` by [passing it down as a prop.](/learn/passing-props-to-a-component) Conversely, the `Panel` component now has *no control* over the value of `isActive`--it's now up to the parent component! +Désormais, le composant parent du `Panel` peut *contrôler* `isActive` en [le passant en tant que prop](/learn/passing-props-to-a-component). À l'inverse, le composant `Panel` *n'a plus le contrôle* sur la valeur de `isActive` — elle est désormais entre les mains du composant parent ! -### Step 2: Pass hardcoded data from the common parent {/*step-2-pass-hardcoded-data-from-the-common-parent*/} +### Étape 2 : passez la valeur codée en dur depuis le parent commun {/*step-2-pass-hardcoded-data-from-the-common-parent*/} -To lift state up, you must locate the closest common parent component of *both* of the child components that you want to coordinate: +Pour faire remonter l'état, vous devez identifier le parent commun le plus proche des *deux* composants enfants que vous souhaitez coordonner : -* `Accordion` *(closest common parent)* +* `Accordion` *(parent commun le plus proche)* - `Panel` - `Panel` -In this example, it's the `Accordion` component. Since it's above both panels and can control their props, it will become the "source of truth" for which panel is currently active. Make the `Accordion` component pass a hardcoded value of `isActive` (for example, `true`) to both panels: +Dans cet exemple, il s'agit du composant `Accordion`. Puisqu'il se situe au-dessus des deux panneaux et qu'il peut contrôler leurs props, il devient la « source de vérité » pour savoir quel panneau est actuellement actif. Faites en sorte que le composant `Accordion` passe la valeur codée en dur de `isActive` (par exemple `true`) aux deux panneaux : @@ -136,11 +137,11 @@ export default function Accordion() { return ( <>

Almaty, Kazakhstan

- - With a population of about 2 million, Almaty is Kazakhstan's largest city. From 1929 to 1997, it was its capital city. + + Avec une population d'environ 2 millions d'habitants, Almaty est la plus grande ville du Kazakhstan. De 1929 à 1997, elle en a été la capitale. - - The name comes from алма, the Kazakh word for "apple" and is often translated as "full of apples". In fact, the region surrounding Almaty is thought to be the ancestral home of the apple, and the wild Malus sieversii is considered a likely candidate for the ancestor of the modern domestic apple. + + Le nom vient de алма, le mot kazakh pour « pomme » ; il est souvent traduit par « pleine de pommes ». En fait, la région entourant Almaty est considérée comme le berceau ancestral de la pomme, et la Malus sieversii sauvage est considérée comme une probable candidate pour être l'ancêtre de la pomme domestique moderne. ); @@ -154,7 +155,7 @@ function Panel({ title, children, isActive }) {

{children}

) : ( )} @@ -172,21 +173,21 @@ h3, p { margin: 5px 0px; }
-Try editing the hardcoded `isActive` values in the `Accordion` component and see the result on the screen. +Modifiez les valeurs de `isActive` codées en dur dans le composant `Accordion` et voyez le résultat à l'écran. -### Step 3: Add state to the common parent {/*step-3-add-state-to-the-common-parent*/} +### Étape 3 : ajoutez l'état au parent commun {/*step-3-add-state-to-the-common-parent*/} -Lifting state up often changes the nature of what you're storing as state. +Faire remonter l'état change souvent la nature de ce que vous y stockez. -In this case, only one panel should be active at a time. This means that the `Accordion` common parent component needs to keep track of *which* panel is the active one. Instead of a `boolean` value, it could use a number as the index of the active `Panel` for the state variable: +Dans cet exemple, un seul panneau doit être actif à un instant donné. Ça signifie que le parent commun `Accordion` doit garder trace de *quel* panneau est actif. Pour la variable d'état, il pourrait utiliser un nombre représentant l'index du `Panel` actif plutôt qu'un `boolean` : ```js const [activeIndex, setActiveIndex] = useState(0); ``` -When the `activeIndex` is `0`, the first panel is active, and when it's `1`, it's the second one. +Quand `activeIndex` vaut `0`, le premier panneau est actif, et quand il vaut `1`, alors c'est le second. -Clicking the "Show" button in either `Panel` needs to change the active index in `Accordion`. A `Panel` can't set the `activeIndex` state directly because it's defined inside the `Accordion`. The `Accordion` component needs to *explicitly allow* the `Panel` component to change its state by [passing an event handler down as a prop](/learn/responding-to-events#passing-event-handlers-as-props): +Le fait d'appuyer sur le bouton « Afficher » dans l'un ou l'autre des `Panel` doit modifier l'index actif dans `Accordion`. Un `Panel` ne peut définir l'état `activeIndex` directement puisqu'il est défini à l'intérieur d'`Accordion`. Ce dernier doit *explicitement autoriser* le composant `Panel` à changer son état en [lui transmettant un gestionnaire d'événement en tant que prop](/learn/responding-to-events#passing-event-handlers-as-props) : ```js <> @@ -205,7 +206,7 @@ Clicking the "Show" button in either `Panel` needs to change the active index in ``` -The ` )} @@ -266,19 +267,19 @@ h3, p { margin: 5px 0px; } -This completes lifting state up! Moving state into the common parent component allowed you to coordinate the two panels. Using the active index instead of two "is shown" flags ensured that only one panel is active at a given time. And passing down the event handler to the child allowed the child to change the parent's state. +Ainsi s'achève la partie pour faire remonter l'état ! Déplacer l'état dans le composant parent commun vous permet de coordonner les deux panneaux. L'utilisation d'un index actif à la place de deux indicateurs « est affiché » garantit qu'un seul panneau est actif à la fois. Enfin, passer le gestionnaire d'événement à l'enfant permet à ce dernier de changer l'état du parent. - + -Initially, `Accordion`'s `activeIndex` is `0`, so the first `Panel` receives `isActive = true` +Au départ, la valeur du `activeIndex` de l'`Accordion` vaut `0`, le premier `Panel` reçoit donc `isActive = true`. - + -When `Accordion`'s `activeIndex` state changes to `1`, the second `Panel` receives `isActive = true` instead +Quant l'état `activeIndex` de l'`Accordion` change à `1`, le second `Panel` reçoit désormais `isActive = true`. @@ -286,48 +287,48 @@ When `Accordion`'s `activeIndex` state changes to `1`, the second `Panel` receiv -#### Controlled and uncontrolled components {/*controlled-and-uncontrolled-components*/} +#### Composants contrôlés et non contrôlés {/*controlled-and-uncontrolled-components*/} -It is common to call a component with some local state "uncontrolled". For example, the original `Panel` component with an `isActive` state variable is uncontrolled because its parent cannot influence whether the panel is active or not. +Il est courant d'appeler « non contrôlé » un composant ayant un état local. Par exemple, le composant `Panel` d'origine avec une variable d'état `isActive` est non contrôlé parce que son parent ne peut pas influencer le fait que le panneau soit actif ou non. -In contrast, you might say a component is "controlled" when the important information in it is driven by props rather than its own local state. This lets the parent component fully specify its behavior. The final `Panel` component with the `isActive` prop is controlled by the `Accordion` component. +À l'inverse, vous pouvez dire qu'un composant est « contrôlé » quand les informations importantes qu'il contient sont pilotées par les props plutôt que par son propre état local. Ça permet au parent de spécifier entièrement son comportement. Le composant final `Panel` avec la prop `isActive` est contrôlé par le composant `Accordion`. -Uncontrolled components are easier to use within their parents because they require less configuration. But they're less flexible when you want to coordinate them together. Controlled components are maximally flexible, but they require the parent components to fully configure them with props. +Les composants non contrôlés sont plus simples d'utilisation au sein de leurs parents puisqu'ils nécessitent moins de configuration. Cependant, ils sont moins flexibles lorsque vous souhaitez les coordonner . Les composants contrôlés sont extrêmement flexibles, mais leurs composants parents doivent les configurer complètement avec des props. -In practice, "controlled" and "uncontrolled" aren't strict technical terms--each component usually has some mix of both local state and props. However, this is a useful way to talk about how components are designed and what capabilities they offer. +Dans la pratique, « contrôlé » et « non contrôlé » ne sont pas des termes techniques stricts — chaque composant dispose généralement d'un mélange entre état local et props. Ça reste une façon pratique de décrire comment les composants sont conçus et les capacités qu'ils offrent. -When writing a component, consider which information in it should be controlled (via props), and which information should be uncontrolled (via state). But you can always change your mind and refactor later. +En écrivant un composant, déterminez quelles informations doivent être contrôlées (*via* les props) ou non contrôlées (*via* l'état). De toutes façons, vous pouvez toujours changer d'avis par la suite et remanier le composant. -## A single source of truth for each state {/*a-single-source-of-truth-for-each-state*/} +## Une source de vérité unique pour chaque état {/*a-single-source-of-truth-for-each-state*/} -In a React application, many components will have their own state. Some state may "live" close to the leaf components (components at the bottom of the tree) like inputs. Other state may "live" closer to the top of the app. For example, even client-side routing libraries are usually implemented by storing the current route in the React state, and passing it down by props! +Dans une application React, de nombreux composants auront leur propre état. Ces derniers peuvent « vivre » à proximité des composants feuilles (les composants en bas de l'arbre) tels que les champs de saisie. D'autres peuvent « vivre » plus proches de la racine de l'appli. Ainsi, même les bibliothèques de routage côté client sont généralement implémentées en stockant la route actuelle dans un état React, puis en la transmettant au travers des props ! -**For each unique piece of state, you will choose the component that "owns" it.** This principle is also known as having a ["single source of truth".](https://en.wikipedia.org/wiki/Single_source_of_truth) It doesn't mean that all state lives in one place--but that for _each_ piece of state, there is a _specific_ component that holds that piece of information. Instead of duplicating shared state between components, *lift it up* to their common shared parent, and *pass it down* to the children that need it. +**Pour chaque élément unique de l'état, vous devrez choisir le composant auquel il va « appartenir ».** Ce principe est également connu comme une [« source de vérité unique »](https://en.wikipedia.org/wiki/Single_source_of_truth) *(lien en anglais, NdT)*. Ça ne signifie pas que tout l'état se situe à un seul endroit mais plutôt que pour _chaque_ élément d'état, il y a un composant _spécifique_ qui détient cet élément. Au lieu de dupliquer un état partagé entre des composants, il faut le *faire remonter* jusqu'à leur parent commun, puis le *passer vers le bas* aux composants qui en ont besoin. -Your app will change as you work on it. It is common that you will move state down or back up while you're still figuring out where each piece of the state "lives". This is all part of the process! +Votre appli évoluera au fur et à mesure que vous y travaillerez. Il est fréquent que vous déplaciez un état vers le bas ou vers le haut alors que vous êtes en train de déterminer où chaque élément de l'état doit « vivre ». Ça fait partie du processus ! -To see what this feels like in practice with a few more components, read [Thinking in React.](/learn/thinking-in-react) +Pour voir ce que ça donne en pratique avec quelques composants supplémentaires, lisez [Penser en React](/learn/thinking-in-react). -* When you want to coordinate two components, move their state to their common parent. -* Then pass the information down through props from their common parent. -* Finally, pass the event handlers down so that the children can change the parent's state. -* It's useful to consider components as "controlled" (driven by props) or "uncontrolled" (driven by state). +* Lorsque vous souhaitez coordonner deux composants, déplacez leur état vers leur parent commun. +* Ensuite, passez l'information vers le bas *via* les props provenant de leur parent commun. +* Enfin, transmettez des gestionnaires d'événements afin que les enfants puissent changer l'état du parent. +* Il est utile de considérer les composants comme étant « contrôlés » (pilotés par les props) ou « non contrôlés » (pilotés par l'état). -#### Synced inputs {/*synced-inputs*/} +#### Saisies synchronisées {/*synced-inputs*/} -These two inputs are independent. Make them stay in sync: editing one input should update the other input with the same text, and vice versa. +Ces deux champs de saisie sont indépendants. Faites en sorte qu'ils soient synchronisés : modifier l'un des champs doit également mettre à jour l'autre champ avec le même texte, et vice-versa. -You'll need to lift their state up into the parent component. +Vous aurez besoin de faire remonter l'état au composant parent. @@ -339,8 +340,8 @@ import { useState } from 'react'; export default function SyncedInputs() { return ( <> - - + + ); } @@ -374,7 +375,7 @@ label { display: block; } -Move the `text` state variable into the parent component along with the `handleChange` handler. Then pass them down as props to both of the `Input` components. This will keep them in sync. +Déplacez la variable d'état `text` dans le parent commun ainsi que le gestionnaire `handleChange`. Ensuite, passez-les vers le bas aux deux composants `Input`. Ils resteront ainsi synchronisés. @@ -391,12 +392,12 @@ export default function SyncedInputs() { return ( <> @@ -427,17 +428,17 @@ label { display: block; } -#### Filtering a list {/*filtering-a-list*/} +#### Filtrer une liste {/*filtering-a-list*/} -In this example, the `SearchBar` has its own `query` state that controls the text input. Its parent `FilterableList` component displays a `List` of items, but it doesn't take the search query into account. +Dans cet exemple, la `SearchBar` dispose de son propre état `query` qui contrôle le champ de saisie. Son composant parent `FilterableList` affiche une `List` d'éléments, mais ne tient pas compte de la recherche. -Use the `filterItems(foods, query)` function to filter the list according to the search query. To test your changes, verify that typing "s" into the input filters down the list to "Sushi", "Shish kebab", and "Dim sum". +Utilisez la fonction `filterItems(foods, query)` pour filtrer la liste selon la requête de recherche. Pour tester vos modifications, vérifiez que le fait de taper « s » dans le champ de filtre réduit la liste aux éléments « Sushi », « Shish kebab » et « Dim sum ». -Note that `filterItems` is already implemented and imported so you don't need to write it yourself! +Remarquez que `filterItems` est déjà implémentée et importée afin que vous n'ayez pas à l'écrire vous-même ! -You will want to remove the `query` state and the `handleChange` handler from the `SearchBar`, and move them to the `FilterableList`. Then pass them down to `SearchBar` as `query` and `onChange` props. +Vous devrez retirer l'état `query` et le gestionnaire `handleChange` de la `SearchBar` puis les déplacer dans `FilterableList`. Transmettez-les ensuite à `SearchBar` en tant que props `query` et `onChange`. @@ -466,7 +467,7 @@ function SearchBar() { return (