diff --git a/content/blog/2016-07-13-mixins-considered-harmful.md b/content/blog/2016-07-13-mixins-considered-harmful.md
index 2ea907ea8..44a1262e2 100644
--- a/content/blog/2016-07-13-mixins-considered-harmful.md
+++ b/content/blog/2016-07-13-mixins-considered-harmful.md
@@ -1,71 +1,71 @@
---
-title: "Mixins Considered Harmful"
+title: "Les mixins sont dangereux"
author: [gaearon]
---
-“How do I share the code between several components?” is one of the first questions that people ask when they learn React. Our answer has always been to use component composition for code reuse. You can define a component and use it in several other components.
+« Comment réutiliser mon code à travers plusieurs composants ? » C’est une des premières questions que les gens se posent quand ils apprennent React. Notre réponse a toujours consisté à utiliser la composition des composants. Vous pouvez définir un composant et l’utiliser dans plusieurs autres composants.
-It is not always obvious how a certain pattern can be solved with composition. React is influenced by functional programming but it came into the field that was dominated by object-oriented libraries. It was hard for engineers both inside and outside of Facebook to give up on the patterns they were used to.
+En fonction du contexte, la solution à base de composition n'est pas toujours évidente. React est influencé par la programmation fonctionnelle mais il est arrivé dans un domaine où les bibliothèques orientées objets étaient monnaie courante. Pour les ingénieurs tant chez Facebook qu'en dehors, abandonner leurs vieux modèles mentaux n’était pas chose aisée.
-To ease the initial adoption and learning, we included certain escape hatches into React. The mixin system was one of those escape hatches, and its goal was to give you a way to reuse code between components when you aren’t sure how to solve the same problem with composition.
+Pour faciliter l’adoption initiale et l'apprentissage, nous avons incorporé quelques échappatoires dans React. Le système de mixins en faisait partie, l’objectif étant de fournir un moyen de réutiliser du code entre plusieurs composants quand vous ne saviez pas trop comment y parvenir avec la composition.
-Three years passed since React was released. The landscape has changed. Multiple view libraries now adopt a component model similar to React. Using composition over inheritance to build declarative user interfaces is no longer a novelty. We are also more confident in the React component model, and we have seen many creative uses of it both internally and in the community.
+Trois ans ont passé depuis que React est sorti. Le paysage a changé. Des tas de bibliothèques d’interfaces utilisateurs (UI) adoptent désormais un modèle de composants similaire à React. Préférer la composition à l'héritage pour construire des UI de façon déclarative n'a plus rien d'une nouveauté. Nous sommes également plus confiants vis-à-vis du modèle de composants de React, et nous avons pu voir de nombreuses utilisations créatives de la bibliothèque tant en interne que dans la communauté.
-In this post, we will consider the problems commonly caused by mixins. Then we will suggest several alternative patterns for the same use cases. We have found those patterns to scale better with the complexity of the codebase than mixins.
+Dans cet article, nous allons examiner les problèmes qu’entraînent couramment les mixins. Nous suggérerons alors plusieurs approches alternatives pour les mêmes cas d'usages. Nous avons constaté que ces approches restent plus maintenables que les mixins lorsque la complexité de la base de code augmente.
-## Why Mixins are Broken {#why-mixins-are-broken}
+## Les problèmes des mixins {#why-mixins-are-broken}
-At Facebook, React usage has grown from a few components to thousands of them. This gives us a window into how people use React. Thanks to declarative rendering and top-down data flow, many teams were able to fix a bunch of bugs while shipping new features as they adopted React.
+Chez Facebook l'utilisation de React est passée de quelques composants à plusieurs milliers. Ça nous offre un bonne vision des façons dont les gens utilisent React. Grâce à un rendu déclaratif et au flux de données descendant, de nombreuses équipes ont pu corriger un paquet de bugs tout en livrant de nouvelles fonctionnalités en adoptant React.
-However it’s inevitable that some of our code using React gradually became incomprehensible. Occasionally, the React team would see groups of components in different projects that people were afraid to touch. These components were too easy to break accidentally, were confusing to new developers, and eventually became just as confusing to the people who wrote them in the first place. Much of this confusion was caused by mixins. At the time, I wasn’t working at Facebook but I came to the [same conclusions](https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750) after writing my fair share of terrible mixins.
+Il est cependant inévitable qu'une partie de notre code utilisant React devienne progressivement incompréhensible. L'équipe React tombait parfois, dans divers projets, sur des groupes de composants que plus personne n'osait toucher. Ces composants étaient trop fragiles, déroutants pour les nouveaux développeurs—et même à terme pour leurs auteurs d'origine. Une large part de cette confusion provenait des mixins. À l'époque, je ne travaillais pas chez Facebook mais j’en étais arrivé aux [mêmes conclusions](https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750) après avoir moi-même écrit ma part de mixins atroces.
-This doesn’t mean that mixins themselves are bad. People successfully employ them in different languages and paradigms, including some functional languages. At Facebook, we extensively use traits in Hack which are fairly similar to mixins. Nevertheless, we think that mixins are unnecessary and problematic in React codebases. Here’s why.
+Ça ne veut pas dire que les mixins en eux-mêmes sont mauvais. Ils sont employés avec succès dans divers langages et paradigmes, dont certains langages fonctionnels. Chez Facebook, nous utilisons énormément les _traits_ dans notre code écrit en Hack, et ceux-ci ressemblent beaucoup aux mixins. Quoi qu'il en soit, nous estimons que les mixins sont superflus et problématiques dans des bases de code React. Voyons pourquoi.
-### Mixins introduce implicit dependencies {#mixins-introduce-implicit-dependencies}
+### Les mixins introduisent des dépendances implicites {#mixins-introduce-implicit-dependencies}
-Sometimes a component relies on a certain method defined in the mixin, such as `getClassName()`. Sometimes it’s the other way around, and mixin calls a method like `renderHeader()` on the component. JavaScript is a dynamic language so it’s hard to enforce or document these dependencies.
+Il arrive qu'un composant s'appuie sur une méthode précise définie dans le mixin, telle que `getClassName()`. D'autres fois c'est l'inverse, et le mixin appelle une méthode du composant, du genre `renderHeader()`. JavaScript est un langage dynamique, de sorte qu'il est difficile de vérifier ou même de documenter ces dépendances.
-Mixins break the common and usually safe assumption that you can rename a state key or a method by searching for its occurrences in the component file. You might write a stateful component and then your coworker might add a mixin that reads this state. In a few months, you might want to move that state up to the parent component so it can be shared with a sibling. Will you remember to update the mixin to read a prop instead? What if, by now, other components also use this mixin?
+Les mixins invalident la supposition habituelle et généralement fiable qu’on peut renommer une clé d'état local ou une méthode en recherchant ses occurrences dans le fichier du composant. Peut-être écrivez-vous un composant à état, après quoi votre collègue y ajoute un mixin qui lit cet état. Dans quelques mois, vous pourriez vouloir faire remonter l'état dans le composant parent, pour qu'il puisse être partagé avec vos éléments frères. Vous rappellerez-vous alors qu'il faut mettre à jour le mixin pour qu'il lise plutôt une prop ? Et si, à ce stade, d'autres composants utilisent le même mixin ?
-These implicit dependencies make it hard for new team members to contribute to a codebase. A component’s `render()` method might reference some method that isn’t defined on the class. Is it safe to remove? Perhaps it’s defined in one of the mixins. But which one of them? You need to scroll up to the mixin list, open each of those files, and look for this method. Worse, mixins can specify their own mixins, so the search can be deep.
+Ces dépendances implicites sont autant d'obstacles empêchant les nouveaux membres de l'équipe de contribuer efficacement à la base de code. La méthode `render()` d'un composant fait peut-être référence à une méthode qui n'est pas définie dans la classe. Peut-on alors la retirer sereinement ? Elle est peut-être définie dans l'un des mixins. Mais lequel ? Vous devez alors remonter jusqu'à la liste des mixins, ouvrir chaque fichier concerné, et y rechercher cette méthode. Pire, les mixins peuvent utiliser leurs propres mixins, ce qui complexifie la recherche.
-Often, mixins come to depend on other mixins, and removing one of them breaks the other. In these situations it is very tricky to tell how the data flows in and out of mixins, and what their dependency graph looks like. Unlike components, mixins don’t form a hierarchy: they are flattened and operate in the same namespace.
+Les mixins en viennent souvent à dépendre d'autres mixins, de sorte qu'en retirer un risque d'en casser d'autres. Dans de telles situations, il devient presque impossible de saisir les flux de données entrants et sortants des mixins, sans parler de leur graphe de dépendance. Contrairement aux composants, les mixins ne forment pas une hiérarchie : ils sont aplatis et opèrent au sein d'un même espace de noms.
-### Mixins cause name clashes {#mixins-cause-name-clashes}
+### Les mixins causent des conflits de nommage {#mixins-cause-name-clashes}
-There is no guarantee that two particular mixins can be used together. For example, if `FluxListenerMixin` defines `handleChange()` and `WindowSizeMixin` defines `handleChange()`, you can’t use them together. You also can’t define a method with this name on your own component.
+Rien ne permet de garantir que deux mixins spécifiques pourront être exploités conjointement. Par exemple, si `FluxListenerMixin` définit `handleChange()` et que `WindowSizeMixin` définit `handleChange()`, vous ne pourrez pas les utiliser ensemble, ni d'ailleurs définir une méthode avec ce nom-là dans votre propre composant.
-It’s not a big deal if you control the mixin code. When you have a conflict, you can rename that method on one of the mixins. However it’s tricky because some components or other mixins may already be calling this method directly, and you need to find and fix those calls as well.
+Ce n'est pas si grave lorsque vous contrôlez le code du mixin. Quand vous rencontrez un conflit, vous pouvez toujours renommer cette méthode dans l'un des mixins. C'est toutefois risqué parce que certains composants ou d'autres mixins font peut-être déjà appel à cette méthode directement, et vous devez débusquer et corriger ces appels-là aussi.
-If you have a name conflict with a mixin from a third party package, you can’t just rename a method on it. Instead, you have to use awkward method names on your component to avoid clashes.
+Si vous avez un conflit de nommage avec un mixin issu d'un module tiers, vous ne pouvez pas simplement renommer sa méthode. Vous devrez plutôt utiliser des noms de méthodes balourds dans votre composant pour éviter les conflits.
-The situation is no better for mixin authors. Even adding a new method to a mixin is always a potentially breaking change because a method with the same name might already exist on some of the components using it, either directly or through another mixin. Once written, mixins are hard to remove or change. Bad ideas don’t get refactored away because refactoring is too risky.
+La vie n'est pas rose non plus pour les auteurs de mixins. Le simple fait d'ajouter une méthode à un mixin porte toujours le risque de casser la compatibilité, parce qu'une méthode avec le même nom pourrait exister dans des composants utilisant votre mixin, soit directement soit via d'autres mixins. Une fois écrits, les mixins sont difficiles à retirer ou modifier. Les mauvaises idées sont rarement éliminées par une refactorisation, parce que celle-ci est généralement trop risquée.
-### Mixins cause snowballing complexity {#mixins-cause-snowballing-complexity}
+### Les mixins font déraper la complexité {#mixins-cause-snowballing-complexity}
-Even when mixins start out simple, they tend to become complex over time. The example below is based on a real scenario I’ve seen play out in a codebase.
+Même quand les mixins démarrent avec un code simple, ils ont tendance à se complexifier avec le temps. L'exemple ci-dessous est basé sur un véritable scénario dont j'ai été témoin dans une base de code.
-A component needs some state to track mouse hover. To keep this logic reusable, you might extract `handleMouseEnter()`, `handleMouseLeave()` and `isHovering()` into a `HoverMixin`. Next, somebody needs to implement a tooltip. They don’t want to duplicate the logic in `HoverMixin` so they create a `TooltipMixin` that uses `HoverMixin`. `TooltipMixin` reads `isHovering()` provided by `HoverMixin` in its `componentDidUpdate()` and either shows or hides the tooltip.
+Un composant a besoin d'un état local pour pister les mouvements du pointeur. Pour permettre la réutilisation de cette logique, vous pourriez extraire `handleMouseEnter()`, `handleMouseLeave()` et `isHovering()` dans un `HoverMixin`. Ensuite, quelqu'un a besoin d'implémenter une infobulle. Il ne veut pas dupliquer le code du `HoverMixin` alors il crée un `TooltipMixin` qui utilise `HoverMixin`. `TooltipMixin` lit le `isHovering()` fourni par `HoverMixin` dans sa méthode `componentDidUpdate()` pour décider d'afficher ou de masquer l'infobulle.
-A few months later, somebody wants to make the tooltip direction configurable. In an effort to avoid code duplication, they add support for a new optional method called `getTooltipOptions()` to `TooltipMixin`. By this time, components that show popovers also use `HoverMixin`. However popovers need a different hover delay. To solve this, somebody adds support for an optional `getHoverOptions()` method and implements it in `TooltipMixin`. Those mixins are now tightly coupled.
+Quelques mois plus tard, quelqu'un veut rendre la direction de l'infobulle configurable. Afin d'éviter la duplication de code, ils ajoutent la prise en charge d'une méthode optionnelle `getTooltipOptions()` dans `TooltipMixin`. À ce stade, les composants qui affichent des encarts au survol utilisent également `HoverMixin`. En revanche, ces derniers ont besoin d'un délai de survol différent. Pour y parvenir, quelqu'un ajoute la prise en charge d'une méthode optionnelle `getHoverOptions()`et l'implémente dans le `TooltipMixin`. Les deux mixins sont désormais fortement couplés.
-This is fine while there are no new requirements. However this solution doesn’t scale well. What if you want to support displaying multiple tooltips in a single component? You can’t define the same mixin twice in a component. What if the tooltips need to be displayed automatically in a guided tour instead of on hover? Good luck decoupling `TooltipMixin` from `HoverMixin`. What if you need to support the case where the hover area and the tooltip anchor are located in different components? You can’t easily hoist the state used by mixin up into the parent component. Unlike components, mixins don’t lend themselves naturally to such changes.
+Ça tient le coup tant que les exigences n'évoluent plus. Ceci dit, cette solution est friable. Et si vous vouliez permettre l'affichage de plusieurs infobulles pour un même composant ? Vous ne pouvez pas définir le même mixin deux fois dans un composant. Et si les infobulles ont besoin d'être affichées automatiquement, lors d'une visite guidée de la page plutôt qu'au survol ? Bonne chance pour découpler le `TooltipMixin` du `HoverMixin`. Et si vous deviez gérer le cas où la zone de survol et le point d'ancrage de l'infobulle appartiennent à des composants différents ? Il est délicat de faire remonter l'état utilisé par le mixin dans le composant parent. Contrairement aux composants, les mixins ne se prêtent pas naturellement à ce genre d'évolutions.
-Every new requirement makes the mixins harder to understand. Components using the same mixin become increasingly coupled with time. Any new capability gets added to all of the components using that mixin. There is no way to split a “simpler” part of the mixin without either duplicating the code or introducing more dependencies and indirection between mixins. Gradually, the encapsulation boundaries erode, and since it’s hard to change or remove the existing mixins, they keep getting more abstract until nobody understands how they work.
+Chaque nouveau besoin rend les mixins plus difficiles à comprendre. Les composants qui utilisent un même mixin sont de plus en plus fortement couplés avec le temps. Toute nouvelle fonctionnalité débarque d'office dans tous les composants utilisant le mixin. Il est impossible d'extraire la partie « plus simple » du mixin sans dupliquer le code ni introduire davantage de dépendances et d'indirections entre les mixins. Progressivement, les frontières de l'encapsulation se délitent, et puisqu'il est difficile de modifier ou même retirer les mixins existants, ils continuent à monter en abstraction jusqu'à ce que plus personne ne comprenne comment ils marchent.
-These are the same problems we faced building apps before React. We found that they are solved by declarative rendering, top-down data flow, and encapsulated components. At Facebook, we have been migrating our code to use alternative patterns to mixins, and we are generally happy with the results. You can read about those patterns below.
+Nous faisions déjà face à ces problématiques de construction d'appli avant React. Nous avons constaté qu'on peut les résoudre avec du rendu déclaratif, un flux de données descendant et des composants encapsulés. Chez Facebook, nous migrons notre code vers des approches alternatives aux mixins, et en général le résultat nous plaît beaucoup. Vous pouvez découvrir ces approches ci-dessous.
-## Migrating from Mixins {#migrating-from-mixins}
+## Sortir des mixins {#migrating-from-mixins}
-Let’s make it clear that mixins are not technically deprecated. If you use `React.createClass()`, you may keep using them. We only say that they didn’t work well for us, and so we won’t recommend using them in the future.
+Pour commencer, précisons que les mixins ne sont pas techniquement dépréciés. Si vous utilisez `React.createClass()`, vous pouvez continuer à vous en servir. Nous disons seulement qu'ils ne nous ont pas satisfaits, donc nous ne recommanderons par leur utilisation à l'avenir. *(Depuis React 15.5, cette méthode a été [sortie dans un module à part](/docs/react-without-es6.html#mixins), NdT.)*
-Every section below corresponds to a mixin usage pattern that we found in the Facebook codebase. For each of them, we describe the problem and a solution that we think works better than mixins. The examples are written in ES5 but once you don’t need mixins, you can switch to ES6 classes if you’d like.
+Chaque section ci-dessous correspond à un schéma d'utilisation des mixins que nous avons rencontré dans la base de code de Facebook. Pour chacune, nous décrivons le problème et une solution que nous estimons supérieure. Les exemples sont écrits en ES5 mais dès lors que vous n'avez plus besoin des mixins, vous pouvez passer à la syntaxe de classe ES6 si vous le souhaitez.
-We hope that you find this list helpful. Please let us know if we missed important use cases so we can either amend the list or be proven wrong!
+Nous espérons que cette liste vous sera utile. N’hésitez pas à nous signaler des cas d'usages importants que nous aurions loupé afin que nous puissions soit augmenter cette liste, soit manger notre chapeau !
-### Performance Optimizations {#performance-optimizations}
+### Optimisation des performances {#performance-optimizations}
-One of the most commonly used mixins is [`PureRenderMixin`](/docs/pure-render-mixin.html). You might be using it in some components to [prevent unnecessary re-renders](/docs/advanced-performance.html#shouldcomponentupdate-in-action) when the props and state are shallowly equal to the previous props and state:
+Un des mixins les plus couramment utilisés est le [`PureRenderMixin`](/docs/pure-render-mixin.html). Vous vous en servez peut-être dans certains composants pour [éviter des rafraîchissements superflus](/docs/advanced-performance.html#shouldcomponentupdate-in-action) quand les props et l'état sont superficiellement égaux à leurs valeurs précédentes :
```javascript
var PureRenderMixin = require('react-addons-pure-render-mixin');
@@ -80,7 +80,7 @@ var Button = React.createClass({
#### Solution {#solution}
-To express the same without mixins, you can use the [`shallowCompare`](/docs/shallow-compare.html) function directly instead:
+Pour faire la même chose sans mixins, vous pouvez utiliser plutôt la fonction [`shallowCompare`](/docs/shallow-compare.html) directement :
```js
var shallowCompare = require('react-addons-shallow-compare');
@@ -95,13 +95,13 @@ var Button = React.createClass({
});
```
-If you use a custom mixin implementing a `shouldComponentUpdate` function with different algorithm, we suggest exporting just that single function from a module and calling it directly from your components.
+Si vous utilisez un mixin personnalisé qui implémente une fonction `shouldComponentUpdate` avec un algorithme différent, nous vous suggérons d'exporter juste cette fonction depuis un module et de l'appeler directement dans votre composant.
-We understand that more typing can be annoying. For the most common case, we plan to [introduce a new base class](https://github.com/facebook/react/pull/7195) called `React.PureComponent` in the next minor release. It uses the same shallow comparison as `PureRenderMixin` does today.
+Nous savons bien qu'il est pénible de devoir écrire davantage de code. Pour le cas le plus courant, nous comptons [fournir une nouvelle classe de base](https://github.com/facebook/react/pull/7195) appelée `React.PureComponent` dans la prochaine version mineure. Elle utilisera la même comparaison de surface que celle de `PureRenderMixin` aujourd’hui *(elle est arrivée avec React 15.3, NdT)*.
-### Subscriptions and Side Effects {#subscriptions-and-side-effects}
+### Abonnements et effets de bord {#subscriptions-and-side-effects}
-The second most common type of mixins that we encountered are mixins that subscribe a React component to a third-party data source. Whether this data source is a Flux Store, an Rx Observable, or something else, the pattern is very similar: the subscription is created in `componentDidMount`, destroyed in `componentWillUnmount`, and the change handler calls `this.setState()`.
+Le deuxième type de mixin le plus courant que nous avons rencontré permet d'abonner un composant React à une source de données tierce. Que la source soit un dépôt Flux, un observable Rx ou quoi que ce soit d'autre, le schéma est toujours le même : on s'abonne dans `componentDidMount`, on se désabonne dans `componentWillUnmount`, et le gestionnaire de changements appelle `this.setState()`.
```javascript
var SubscriptionMixin = {
@@ -130,7 +130,7 @@ var CommentList = React.createClass({
mixins: [SubscriptionMixin],
render: function() {
- // Reading comments from state managed by mixin.
+ // On lit les commentaires depuis l’état géré par le mixin.
var comments = this.state.comments;
return (
@@ -147,48 +147,48 @@ module.exports = CommentList;
#### Solution {#solution-1}
-If there is just one component subscribed to this data source, it is fine to embed the subscription logic right into the component. Avoid premature abstractions.
+Si un seul composant est abonné à la source de données, vous pouvez tout à fait incorporer la logique d'abonnement directement dans ce composant. Il est toujours préférable d’éviter les abstractions prématurées.
-If several components used this mixin to subscribe to a data source, a nice way to avoid repetition is to use a pattern called [“higher-order components”](https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750). It can sound intimidating so we will take a closer look at how this pattern naturally emerges from the component model.
+Si plusieurs composants utilisent le mixin pour s'abonner à la source de données, une manière élégante d'éviter de se répéter consiste à utiliser une approche appelée [« composants d’ordre supérieur »](https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750) *(Higher-Order Components ou HOC, NdT)*. Le terme peut faire peur mais nous allons voir ensemble à quel point cette approche découle naturellement du modèle de composants.
-#### Higher-Order Components Explained {#higher-order-components-explained}
+#### Comprendre les composants d'ordre supérieur {#higher-order-components-explained}
-Let’s forget about React for a second. Consider these two functions that add and multiply numbers, logging the results as they do that:
+Oublions React un instant. Prenez ces deux fonctions qui ajoutent et multiplient des nombres, en journalisant leurs résultats au fil de l’eau :
```js
function addAndLog(x, y) {
var result = x + y;
- console.log('result:', result);
+ console.log('Résultat :', result);
return result;
}
function multiplyAndLog(x, y) {
var result = x * y;
- console.log('result:', result);
+ console.log('Résultat :', result);
return result;
}
```
-These two functions are not very useful but they help us demonstrate a pattern that we can later apply to components.
+Ces deux fonctions ne sont pas très utiles mais elles vont nous aider à illustrer une approche que nous pourrons ensuite appliquer aux composants.
-Let’s say that we want to extract the logging logic out of these functions without changing their signatures. How can we do this? An elegant solution is to write a [higher-order function](https://en.wikipedia.org/wiki/Higher-order_function), that is, a function that takes a function as an argument and returns a function.
+Disons que nous voulons extraire leur logique de journalisation sans changer leurs signatures. Comment y parvenir ? Une solution élégante consiste à écrire une [fonction d’ordre supérieur](https://fr.wikipedia.org/wiki/Fonction_d%27ordre_supérieur), c'est-à-dire une fonction qui prend une fonction en argument et qui renvoie une fonction.
-Again, it sounds more intimidating than it really is:
+Là aussi, ça semble compliqué mais le code reste raisonnable :
```js
function withLogging(wrappedFunction) {
- // Return a function with the same API...
+ // Renvoie une fonction avec la même API...
return function(x, y) {
- // ... that calls the original function
+ // ...qui appelle la fonction d’origine...
var result = wrappedFunction(x, y);
- // ... but also logs its result!
- console.log('result:', result);
+ // ...mais qui logue en prime son résultat !
+ console.log('Résultat :', result);
return result;
};
}
```
-The `withLogging` higher-order function lets us write `add` and `multiply` without the logging statements, and later wrap them to get `addAndLog` and `multiplyAndLog` with exactly the same signatures as before:
+La fonction d'ordre supérieur `withLogging` nous permet d'écrire `add` et `multiply` sans le code de journalisation, et de les enrober plus tard afin d'obtenir `addAndLog` et `multiplyAndLog`, qui auront exactement les mêmes signatures qu’avant :
```js
function add(x, y) {
@@ -202,28 +202,28 @@ function multiply(x, y) {
function withLogging(wrappedFunction) {
return function(x, y) {
var result = wrappedFunction(x, y);
- console.log('result:', result);
+ console.log('Résultat :', result);
return result;
};
}
-// Equivalent to writing addAndLog by hand:
+// Revient à écrire addAndLog à la main :
var addAndLog = withLogging(add);
-// Equivalent to writing multiplyAndLog by hand:
+// Revient à écrire multiplyAndLog à la main :
var multiplyAndLog = withLogging(multiply);
```
-Higher-order components are a very similar pattern, but applied to components in React. We will apply this transformation from mixins in two steps.
+Les composants d'ordre supérieur sont une approche très similaire, mais pour les composants dans React. Nous allons appliquer cette transformation à partir de la version basée sur les mixins en deux étapes.
-As a first step, we will split our `CommentList` component in two, a child and a parent. The child will be only concerned with rendering the comments. The parent will set up the subscription and pass the up-to-date data to the child via props.
+Pour commencer, nous découperons notre composant `CommentList` en deux : un enfant et un parent. L’enfant s'occupera uniquement de l'affichage des commentaires, tandis que le parent s'occupera de l'abonnement et de transmettre des données à jour à son enfant via le mécanisme usuel des props.
```js
-// This is a child component.
-// It only renders the comments it receives as props.
+// Voici le composant enfant.
+// Il se contente d’afficher les commentaires qu’il reçoit via ses props.
var CommentList = React.createClass({
render: function() {
- // Note: now reading from props rather than state.
+ // Remarque : on lit désormais les props et non l’état local.
var comments = this.props.comments;
return (
@@ -235,8 +235,8 @@ var CommentList = React.createClass({
}
});
-// This is a parent component.
-// It subscribes to the data source and renders
.
+// Voici le composant parent.
+// Il gère l’abonnement à la source de données et utilise
pour son rendu.
var CommentListWithSubscription = React.createClass({
getInitialState: function() {
return {
@@ -259,7 +259,7 @@ var CommentListWithSubscription = React.createClass({
},
render: function() {
- // We pass the current state as props to CommentList.
+ // Nous passons l’état local à CommentList via ses props.
return
;
}
});
@@ -267,22 +267,22 @@ var CommentListWithSubscription = React.createClass({
module.exports = CommentListWithSubscription;
```
-There is just one final step left to do.
+Il ne nous reste plus qu'une dernière chose à faire.
-Remember how we made `withLogging()` take a function and return another function wrapping it? We can apply a similar pattern to React components.
+Vous vous rappelez comment nous avions écrit `withLogging()` pour qu'elle accepte une fonction et renvoie une autre fonction qui l'enrobait ? Nous pouvons appliquer une approche similaire aux composants React.
-We will write a new function called `withSubscription(WrappedComponent)`. Its argument could be any React component. We will pass `CommentList` as `WrappedComponent`, but we could also apply `withSubscription()` to any other component in our codebase.
+Nous allons écrire une fonction `withSubscription(WrappedComponent)`. Son argument peut être n'importe quel composant React. Nous lui passerons `CommentList` comme `WrappedComponent`, mais on pourrait aussi appeler `withSubscription` avec n’importe quel composant de notre base de code.
-This function would return another component. The returned component would manage the subscription and render `
` with the current data.
+Cette fonction nous renverra un autre composant. Le composant renvoyé gérera l'abonnement et utilisera `
` pour son rendu, en lui transmettant les données actuelles.
-We call this pattern a “higher-order component”.
+Nous appelons cette approche un « composant d’ordre supérieur ».
-The composition happens at React rendering level rather than with a direct function call. This is why it doesn’t matter whether the wrapped component is defined with `createClass()`, as an ES6 class or a function. If `WrappedComponent` is a React component, the component created by `withSubscription()` can render it.
+La composition a lieu au niveau du rendu de React plutôt qu’avec un appel de fonction direct. C’est pourquoi on se fiche de savoir si le composant enrobé est défini avec `createClass()`, une classe ES6 ou une fonction. Si `WrappedComponent` est un composant React, le composant créé par `withSubscription()` peut l'utiliser.
```js
-// This function takes a component...
+// Cette fonction accepte un composant...
function withSubscription(WrappedComponent) {
- // ...and returns another component...
+ // ...et renvoie un autre composant...
return React.createClass({
getInitialState: function() {
return {
@@ -291,7 +291,7 @@ function withSubscription(WrappedComponent) {
},
componentDidMount: function() {
- // ... that takes care of the subscription...
+ // ...qui s'occupe de gérer l’abonnement...
DataSource.addChangeListener(this.handleChange);
},
@@ -306,14 +306,14 @@ function withSubscription(WrappedComponent) {
},
render: function() {
- // ... and renders the wrapped component with the fresh data!
+ // ...et utilise le composant enrobé, avec des données à jour pour son rendu !
return
;
}
});
}
```
-Now we can declare `CommentListWithSubscription` by applying `withSubscription` to `CommentList`:
+Nous pouvons maintenant déclarer `CommentListWithSubscription` en appliquant `withSubscription` à `CommentList` :
```js
var CommentList = React.createClass({
@@ -329,19 +329,20 @@ var CommentList = React.createClass({
}
});
-// withSubscription() returns a new component that
-// is subscribed to the data source and renders
-//
with up-to-date data.
+// withSubscription() renvoie un nouveau composant qui
+// est abonné à la source de données et utilise
+//
avec des données à jour pour son rendu.
var CommentListWithSubscription = withSubscription(CommentList);
-// The rest of the app is interested in the subscribed component
-// so we export it instead of the original unwrapped CommentList.
+// Le reste de l’appli ne s’intéresse qu’au composant abonné
+// alors nous l’exportons lui plutôt que le composant CommentList
+// original, non-enrobé.
module.exports = CommentListWithSubscription;
```
-#### Solution, Revisited {#solution-revisited}
+#### Solution revisitée {#solution-revisited}
-Now that we understand higher-order components better, let’s take another look at the complete solution that doesn’t involve mixins. There are a few minor changes that are annotated with inline comments:
+À présent que nous comprenons mieux les composants d’ordre supérieur, regardons à nouveau la solution complète qui se passe des mixins. On y trouve quelques menus changements décrits dans les commentaires :
```js
function withSubscription(WrappedComponent) {
@@ -367,14 +368,15 @@ function withSubscription(WrappedComponent) {
},
render: function() {
- // Use JSX spread syntax to pass all props and state down automatically.
+ // Utilise la syntaxe de décomposition (spread) JSX pour transmettre
+ // automatiquement toutes les props ainsi que l'état.
return
;
}
});
}
-// Optional change: convert CommentList to a function component
-// because it doesn't use lifecycle methods or state.
+// Optionnel : on convertit CommentList en fonction composant
+// puisqu’il n’utilise plus ni cycle de vie ni état local.
function CommentList(props) {
var comments = props.comments;
return (
@@ -386,29 +388,29 @@ function CommentList(props) {
)
}
-// Instead of declaring CommentListWithSubscription,
-// we export the wrapped component right away.
+// Au lieu de déclarer CommentListWithSubscription,
+// on peut exporter à la volée le composant enrobé.
module.exports = withSubscription(CommentList);
```
-Higher-order components are a powerful pattern. You can pass additional arguments to them if you want to further customize their behavior. After all, they are not even a feature of React. They are just functions that receive components and return components that wrap them.
+Les composants d'ordre supérieur sont une approche puissante. Vous pouvez leur passer des arguments supplémentaires pour personnaliser leur comportement. Après tout, il ne s'agit même pas d'une fonctionnalité de React : ce sont juste des fonctions qui reçoivent des composants et en renvoient d’autres qui les enrobent.
-Like any solution, higher-order components have their own pitfalls. For example, if you heavily use [refs](/docs/more-about-refs.html), you might notice that wrapping something into a higher-order component changes the ref to point to the wrapping component. In practice we discourage using refs for component communication so we don’t think it’s a big issue. In the future, we might consider adding [ref forwarding](https://github.com/facebook/react/issues/4213) to React to solve this annoyance.
+Comme toute solution, les composants d'ordre supérieur ont leurs propres pièges. Par exemple, si vous utilisez massivement les [refs](/docs/refs-and-the-dom.html), vous remarquerez peut-être qu’enrober quelque chose dans un composant d'ordre supérieure modifie la ref de sorte qu'elle pointe sur le composant d'enrobage. En pratique, nous décourageons le recours aux refs pour faire communiquer les composants et ne pensons donc pas que c'est un problème majeur. À l'avenir, nous envisagerons peut-être d’ajouter [du transfert de refs](https://github.com/facebook/react/issues/4213) dans React pour éliminer cette irritation. *([Ils l'ont effectivement ajouté](/docs/forwarding-refs.html) avec React 16.3, NdT.)*
-### Rendering Logic {#rendering-logic}
+### Logique de rendu {#rendering-logic}
-The next most common use case for mixins that we discovered in our codebase is sharing rendering logic between components.
+Un autre cas d’usage courant des mixins que nous avons repéré dans notre base de code cherche à réutiliser de la logique de rendu entre plusieurs composants.
-Here is a typical example of this pattern:
+Voici un exemple typique de ce schéma :
```js
var RowMixin = {
- // Called by components from render()
+ // Appelé par les composants depuis `render()`
renderHeader: function() {
return (
- {this.getHeaderText() /* Defined by components */}
+ {this.getHeaderText() /* Défini par les composants */}
);
@@ -418,7 +420,7 @@ var RowMixin = {
var UserRow = React.createClass({
mixins: [RowMixin],
- // Called by RowMixin.renderHeader()
+ // Appelé par `RowMixin.renderHeader()`
getHeaderText: function() {
return this.props.user.fullName;
},
@@ -426,7 +428,7 @@ var UserRow = React.createClass({
render: function() {
return (
- {this.renderHeader() /* Defined by RowMixin */}
+ {this.renderHeader() /* Défini par `RowMixin` */}
{this.props.user.biography}
)
@@ -434,15 +436,15 @@ var UserRow = React.createClass({
});
```
-Multiple components may be sharing `RowMixin` to render the header, and each of them would need to define `getHeaderText()`.
+Plusieurs composants pourraient utiliser `RowMixin` pour afficher l’en-tête, et chacun d'entre eux aurait besoin de définir `getHeaderText()`.
#### Solution {#solution-2}
-If you see rendering logic inside a mixin, it’s time to extract a component!
+Si vous remarquez de la logique de rendu dans un mixin, ça veut dire que c’est le moment d'extraire un composant !
-Instead of `RowMixin`, we will define a `
` component. We will also replace the convention of defining a `getHeaderText()` method with the standard mechanism of top-data flow in React: passing props.
+Au lieu de `RowMixin`, nous allons définir un composant ``. Nous remplacerons aussi les conventions d'appel (comme la méthode `getHeaderText()`) par le mécanisme standard de flux de données descendant de React : passer des props.
-Finally, since neither of those components currently need lifecycle methods or state, we can declare them as simple functions:
+Pour finir, vu qu’aucun des composants concernés n’a besoin de cycle de vie ou d’état local, nous pouvons les déclarer comme de simples fonctions :
```js
function RowHeader(props) {
@@ -463,17 +465,17 @@ function UserRow(props) {
}
```
-Props keep component dependencies explicit, easy to replace, and enforceable with tools like [Flow](https://flowtype.org/) and [TypeScript](https://www.typescriptlang.org/).
+Les props permettent aux composants d’exprimer des dépendances explicites, faciles à remplacer, et vérifiables avec des outils tels que [Flow](https://flowtype.org/) et [TypeScript](https://www.typescriptlang.org/).
-> **Note:**
+>Remarque
>
-> Defining components as functions is not required. There is also nothing wrong with using lifecycle methods and state—they are first-class React features. We use function components in this example because they are easier to read and we didn’t need those extra features, but classes would work just as fine.
+>Vous n’êtes pas obligé·e de définir vos composants en tant que fonctions. Il n’y a rien de mal à utiliser des méthodes de cycle de vie ou l’état local : ce sont là des fonctionnalités à part entière de React. Nous utilisons des fonctions composants dans cet exemple parce qu'elles sont plus faciles à lire et que nous n'avions pas l'utilité de ces fonctionnalités supplémentaires, mais ça marchera tout aussi bien avec des classes.
-### Context {#context}
+### Contexte {#context}
-Another group of mixins we discovered were helpers for providing and consuming [React context](/docs/context.html). Context is an experimental unstable feature, has [certain issues](https://github.com/facebook/react/issues/2517), and will likely change its API in the future. We don’t recommend using it unless you’re confident there is no other way of solving your problem.
+Nous avons aussi remarqué une autre catégorie de mixins, qui étaient des utilitaires pour interagir avec le [Contexte React](/docs/context.html). Le Contexte est une fonctionnalité expérimentale instable qui a [quelques soucis](https://github.com/facebook/react/issues/2517), et nous changerons sans doute son API à l’avenir *([ce qu’ils ont fait avec React 16.3](https://fr.reactjs.org/blog/2018/03/29/react-v-16-3.html#official-context-api), NdT)*. Nous déconseillons de l’utiliser à moins que vous soyez certain·e qu’il représente la seule solution à votre problème.
-Nevertheless, if you already use context today, you might have been hiding its usage with mixins like this:
+Toujours est-il que si vous utilisez déjà le contexte, vous avez peut-être masqué son utilisation à l'aide de mixins similaires à celui-ci :
```js
var RouterMixin = {
@@ -481,8 +483,8 @@ var RouterMixin = {
router: React.PropTypes.object.isRequired
},
- // The mixin provides a method so that components
- // don't have to use the context API directly.
+ // Le mixin fournit une méthode pour que les composants
+ // n’aient pas à utiliser l’API de contexte directement.
push: function(path) {
this.context.router.push(path)
}
@@ -494,7 +496,7 @@ var Link = React.createClass({
handleClick: function(e) {
e.stopPropagation();
- // This method is defined in RouterMixin.
+ // Cette méthode est définie dans `RouterMixin`.
this.push(this.props.to);
},
@@ -512,9 +514,9 @@ module.exports = Link;
#### Solution {#solution-3}
-We agree that hiding context usage from consuming components is a good idea until the context API stabilizes. However, we recommend using higher-order components instead of mixins for this.
+Nous sommes d'accord : masquer l'utilisation du contexte aux yeux des composants qui le consomment est une bonne idée jusqu'à ce que l'API de contexte se stabilise. Néanmoins, nous recommandons plutôt de recourir aux composants d'ordre supérieur pour ça.
-Let the wrapping component grab something from the context, and pass it down with props to the wrapped component:
+Le composant d'enrobage récupèrerait l'info depuis le contexte, et la transmettrait via les props au composant enrobé :
```js
function withRouter(WrappedComponent) {
@@ -524,8 +526,8 @@ function withRouter(WrappedComponent) {
},
render: function() {
- // The wrapper component reads something from the context
- // and passes it down as a prop to the wrapped component.
+ // Le composant d’enrobage lit l’information depuis le contexte
+ // et la transmet via les props au composant enrobé.
var router = this.context.router;
return ;
}
@@ -536,7 +538,7 @@ var Link = React.createClass({
handleClick: function(e) {
e.stopPropagation();
- // The wrapped component uses props instead of context.
+ // Le composant enrobé utilise les props au lieu du contexte.
this.props.router.push(this.props.to);
},
@@ -549,15 +551,15 @@ var Link = React.createClass({
}
});
-// Don't forget to wrap the component!
+// N’oubliez pas d’enrober le composant !
module.exports = withRouter(Link);
```
-If you’re using a third party library that only provides a mixin, we encourage you to file an issue with them linking to this post so that they can provide a higher-order component instead. In the meantime, you can create a higher-order component around it yourself in exactly the same way.
+Si vous utilisez une bibliothèque tierce qui ne fournit qu’un mixin, nous vous encourageons à leur signaler le problème dans un ticket avec un lien vers cet article pour qu’ils puissent plutôt fournir un composant d’ordre supérieur. En attendant, vous pouvez créer vous-même un composant d'ordre supérieur qui se comportera exactement pareil.
-### Utility Methods {#utility-methods}
+### Méthodes utilitaires {#utility-methods}
-Sometimes, mixins are used solely to share utility functions between components:
+Parfois les mixins sont utilisés uniquement pour réutiliser des fonctions utilitaires d'un composant à l'autre :
```js
var ColorMixin = {
@@ -586,7 +588,7 @@ var Button = React.createClass({
#### Solution {#solution-4}
-Put utility functions into regular JavaScript modules and import them. This also makes it easier to test them or use them outside of your components:
+Placez les fonctions utilitaires dans des modules JavaScript classiques et importez-les. Ça les rend d'ailleurs plus faciles à tester et à utiliser hors de vos composants :
```js
var getLuminance = require('../utils/getLuminance');
@@ -603,12 +605,12 @@ var Button = React.createClass({
});
```
-### Other Use Cases {#other-use-cases}
+### Autres cas d'usages {#other-use-cases}
-Sometimes people use mixins to selectively add logging to lifecycle methods in some components. In the future, we intend to provide an [official DevTools API](https://github.com/facebook/react/issues/5306) that would let you implement something similar without touching the components. However it’s still very much a work in progress. If you heavily depend on logging mixins for debugging, you might want to keep using those mixins for a little longer.
+Il arrive qu'on utilise les mixins pour ajouter sélectivement de la journalisation ou des méthodes de cycle de vie à certains composants. À l'avenir nous comptons fournir une [API DevTools officielle](https://github.com/facebook/react/issues/5306) qui vous permettra d’implémenter quelque chose de similaire sans toucher aux composants. Ce chantier n'est toutefois pas près d'aboutir. Si vous vous reposez massivement sur les mixins de journalisation pour votre débogage, vous voudrez peut-être les garder sous le coude encore un moment.
-If you can’t accomplish something with a component, a higher-order component, or a utility module, it could be mean that React should provide this out of the box. [File an issue](https://github.com/facebook/react/issues/new) to tell us about your use case for mixins, and we’ll help you consider alternatives or perhaps implement your feature request.
+Si vous n'arrivez pas à vos fins avec un composant, un composant d'ordre supérieur ou un module utilitaire, ça pourrait vouloir dire que React devrait répondre à votre besoin par défaut. [Créez un ticket](https://github.com/facebook/react/issues/new) pour nous expliquer votre cas d'usage des mixins, et nous vous aiderons à explorer des alternatives, ou peut-être implémenterons-nous la fonctionnalité dont vous avez besoin.
-Mixins are not deprecated in the traditional sense. You can keep using them with `React.createClass()`, as we won’t be changing it further. Eventually, as ES6 classes gain more adoption and their usability problems in React are solved, we might split `React.createClass()` into a separate package because most people wouldn’t need it. Even in that case, your old mixins would keep working.
+Les mixins ne sont pas dépréciés au sens traditionnel du terme. Vous pouvez continuer à vous en servir avec `React.createClass()` car leur API est désormais gelée. À mesure que les classes ES6 seront plus répandues et que leurs problèmes d'utilisabilité dans React seront réglés, nous sortirons peut-être `React.createClass()` dans un module à part car la plupart des gens n'en auront plus besoin *([ils l'ont fait avec React 15.5](/docs/react-without-es6.html#mixins), NdT)*. Même dans ce cas, vos vieux mixins continueront à marcher.
-We believe that the alternatives above are better for the vast majority of cases, and we invite you to try writing React apps without using mixins.
+Nous sommes convaincus que les alternatives ci-dessus leur sont supérieures dans la vaste majorité des cas, et nous vous invitons à essayer d'écrire vos applis React sans mixins.