From 668c6369de9588c7e256827e014b788220a4acc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Sun, 24 Feb 2019 09:30:35 +0100 Subject: [PATCH 01/31] Translate HOC title and intro --- content/docs/higher-order-components.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index a7a123abe..41831b6f5 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -1,15 +1,16 @@ --- id: higher-order-components -title: Higher-Order Components +title: Composants d'Ordre Supérieurs permalink: docs/higher-order-components.html --- -A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React's compositional nature. +Un composant d'ordre supérieur (HOC) est une technique avancée de React qui permet de réutiliser la logique de composants. Les HOC ne font pas partie de l'API de React en soi, mais émergent de la nature compositionnelle de React. -Concretely, **a higher-order component is a function that takes a component and returns a new component.** +Concrètement, **un composant d'ordre supérieur est une fonction qui accepte un composant et renvoie un nouveau composant.** ```js -const EnhancedComponent = higherOrderComponent(WrappedComponent); +const ComposantAmeliore = composantdOrdreSuperieur(ComposantInterne); +// const EnhancedComponent = higherOrderComponent(WrappedComponent); ``` Whereas a component transforms props into UI, a higher-order component transforms a component into another component. From 0ebb269165db471a0a7539027600fffea0c9df53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Sun, 24 Feb 2019 09:37:38 +0100 Subject: [PATCH 02/31] Fix typo in title --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 41831b6f5..903c14a2f 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -1,6 +1,6 @@ --- id: higher-order-components -title: Composants d'Ordre Supérieurs +title: Composants d'Ordre Supérieur permalink: docs/higher-order-components.html --- From d1f3dae859c8cb6c05b9b27cb9bc650fc97ed4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Sun, 24 Feb 2019 09:51:58 +0100 Subject: [PATCH 03/31] Translate title in nav --- content/docs/nav.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/nav.yml b/content/docs/nav.yml index 6d657f17e..7a476158f 100644 --- a/content/docs/nav.yml +++ b/content/docs/nav.yml @@ -50,7 +50,7 @@ - id: fragments title: Fragments - id: higher-order-components - title: Higher-Order Components + title: Composants d'Ordre Supérieur - id: integrating-with-other-libraries title: Integrating with Other Libraries - id: jsx-in-depth From 9a393408326e3177c19f1817b1ecd79e246a947d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Sun, 24 Feb 2019 10:22:30 +0100 Subject: [PATCH 04/31] Remove title capitalization --- content/docs/higher-order-components.md | 2 +- content/docs/nav.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 903c14a2f..45f4c843c 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -1,6 +1,6 @@ --- id: higher-order-components -title: Composants d'Ordre Supérieur +title: Composants d'ordre supérieur permalink: docs/higher-order-components.html --- diff --git a/content/docs/nav.yml b/content/docs/nav.yml index 7a476158f..5a6a1eec2 100644 --- a/content/docs/nav.yml +++ b/content/docs/nav.yml @@ -50,7 +50,7 @@ - id: fragments title: Fragments - id: higher-order-components - title: Composants d'Ordre Supérieur + title: Composants d'ordre supérieur - id: integrating-with-other-libraries title: Integrating with Other Libraries - id: jsx-in-depth From 115b5cbbc87aaef68793fef7c0e0a4208d0b6513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Sun, 24 Feb 2019 10:52:01 +0100 Subject: [PATCH 05/31] Translate cross-cutting concerns note and intro --- content/docs/higher-order-components.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 45f4c843c..81a2b8092 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -13,21 +13,21 @@ const ComposantAmeliore = composantdOrdreSuperieur(ComposantInterne); // const EnhancedComponent = higherOrderComponent(WrappedComponent); ``` -Whereas a component transforms props into UI, a higher-order component transforms a component into another component. +Là où un composant transforme des props en interface utilisateur, un composant d'ordre supérieur transforme un composant en un autre composant. -HOCs are common in third-party React libraries, such as Redux's [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) and Relay's [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html). +Les HOC sont courants dans des bibliothèques tierces de React, comme [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) dans Redux et [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) dans Relay. -In this document, we'll discuss why higher-order components are useful, and how to write your own. +Dans ce guide, nous verrons pourquoi les composants d'ordre supérieurs sont utiles, et comment créer le vôtre. -## Use HOCs For Cross-Cutting Concerns {#use-hocs-for-cross-cutting-concerns} +## Utiliser les HOC pour les préoccupations transversales {#use-hocs-for-cross-cutting-concerns} > **Note** > -> We previously recommended mixins as a way to handle cross-cutting concerns. We've since realized that mixins create more trouble than they are worth. [Read more](/blog/2016/07/13/mixins-considered-harmful.html) about why we've moved away from mixins and how you can transition your existing components. +> Nous recommandions dans le passé d'employer des mixins pour gérer les préoccupations transversales. Depuis, nous nous sommes rendus compte que les mixins créent plus de problèmes qu'ils n'en résolvent. [Lisez-en plus](/blog/2016/07/13/mixins-considered-harmful.html) sur pourquoi nous avons renoncé aux mixins, et comment vous pouvez faire de même pour vos composants existants. -Components are the primary unit of code reuse in React. However, you'll find that some patterns aren't a straightforward fit for traditional components. +Les composants React constituent le moyen le plus primaire de réutiliser du code. Cependant, vous remarquerez que les composants classiques ne conviennent pas à tous les modèles. -For example, say you have a `CommentList` component that subscribes to an external data source to render a list of comments: +Imaginez par exemple un composant `CommentList` qui se connecte à une source externe de données pour faire le rendu d'une liste de commentaires : ```js class CommentList extends React.Component { From b9e9187adaf19bf93caa761d1574c8211ecf953d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Sun, 24 Feb 2019 10:52:25 +0100 Subject: [PATCH 06/31] Revert code snippet translation --- content/docs/higher-order-components.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 81a2b8092..1061d8c1d 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -9,8 +9,7 @@ Un composant d'ordre supérieur (HOC) est une technique avancée de React qui pe Concrètement, **un composant d'ordre supérieur est une fonction qui accepte un composant et renvoie un nouveau composant.** ```js -const ComposantAmeliore = composantdOrdreSuperieur(ComposantInterne); -// const EnhancedComponent = higherOrderComponent(WrappedComponent); +const EnhancedComponent = higherOrderComponent(WrappedComponent); ``` Là où un composant transforme des props en interface utilisateur, un composant d'ordre supérieur transforme un composant en un autre composant. From b1a8ec605fb39a0f37446fc71a03448f26920da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Sun, 24 Feb 2019 11:09:45 +0100 Subject: [PATCH 07/31] Translate code snippets comments --- content/docs/higher-order-components.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 1061d8c1d..b31b1c239 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -26,7 +26,7 @@ Dans ce guide, nous verrons pourquoi les composants d'ordre supérieurs sont uti Les composants React constituent le moyen le plus primaire de réutiliser du code. Cependant, vous remarquerez que les composants classiques ne conviennent pas à tous les modèles. -Imaginez par exemple un composant `CommentList` qui se connecte à une source externe de données pour faire le rendu d'une liste de commentaires : +Imaginez que vous ayez créé un composant `CommentList` qui écoute une source externe de données pour faire le rendu d'une liste de commentaires : ```js class CommentList extends React.Component { @@ -34,23 +34,23 @@ class CommentList extends React.Component { super(props); this.handleChange = this.handleChange.bind(this); this.state = { - // "DataSource" is some global data source + // "DataSource" est une source de données quelconque comments: DataSource.getComments() }; } componentDidMount() { - // Subscribe to changes + // Crée un écouteur d'événement DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { - // Clean up listener + // Nettoie l'écouteur d'événement DataSource.removeChangeListener(this.handleChange); } handleChange() { - // Update component state whenever the data source changes + // Met à jour l'état local quand la source de données est modifiée this.setState({ comments: DataSource.getComments() }); @@ -68,7 +68,7 @@ class CommentList extends React.Component { } ``` -Later, you write a component for subscribing to a single blog post, which follows a similar pattern: +Ensuite, vous créez un composant qui gère les événements pour un unique article, et dont la structure est similaire à la précédente : ```js class BlogPost extends React.Component { From e6e1e5b7abf12380cb0e5b8a7d8910c70665c379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Sat, 9 Mar 2019 20:38:25 +0100 Subject: [PATCH 08/31] Finish translation of "Use HOCs For Cross-Cutting Concerns" --- content/docs/higher-order-components.md | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index b31b1c239..706256aa8 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -68,7 +68,7 @@ class CommentList extends React.Component { } ``` -Ensuite, vous créez un composant qui gère les événements pour un unique article, et dont la structure est similaire à la précédente : +Ensuite, vous créez un composant `BlogPost` qui gère les événements pour un unique article, et dont la structure est similaire à la précédente : ```js class BlogPost extends React.Component { @@ -100,15 +100,15 @@ class BlogPost extends React.Component { } ``` -`CommentList` and `BlogPost` aren't identical — they call different methods on `DataSource`, and they render different output. But much of their implementation is the same: +`CommentList` et `BlogPost` ne sont pas identiques—ils appellent des méthodes différentes sur `DataSource`, et font différents rendus. Pourtant une grande partie de leur fonctionnement est la même: -- On mount, add a change listener to `DataSource`. -- Inside the listener, call `setState` whenever the data source changes. -- On unmount, remove the change listener. +- Au montage *(quand le composant entre dans la couche d'affichage, NdT)*, ils ajoutent un écouteur d'événement à `DataSource`. +- Dans l'écouteur, ils appellent `setState` quand la source de données est modifiée. +- Au démontage *(quand le composant sort de la couche d'affichage, NdT)*, ils enlèvent l'écouteur d'événement. -You can imagine that in a large app, this same pattern of subscribing to `DataSource` and calling `setState` will occur over and over again. We want an abstraction that allows us to define this logic in a single place and share it across many components. This is where higher-order components excel. +Vous imaginez bien que dans une appli importante, ce motif d'écoute de `DataSource` et d'appel à `setState` sera récurrent. Il nous faut une abstraction qui nous permette de définir cette logique à un seul endroit et de la partager parmi de nombreux composants. C'est là que les composants d'ordre supérieur entrent en jeu. -We can write a function that creates components, like `CommentList` and `BlogPost`, that subscribe to `DataSource`. The function will accept as one of its arguments a child component that receives the subscribed data as a prop. Let's call the function `withSubscription`: +Vous pouvez donc écrire une fonction pour créer des composants qui écoutent `DataSource`, comme `CommentList` et `BlogPost`. L'un des arguments qu'accepte la fonction est un composant enfant, qui recevra les données écoutées en props. Appelons cette fonction `withSubscription`: ```js const CommentListWithSubscription = withSubscription( @@ -122,14 +122,14 @@ const BlogPostWithSubscription = withSubscription( ); ``` -The first parameter is the wrapped component. The second parameter retrieves the data we're interested in, given a `DataSource` and the current props. +Le premier paramètre est le composant enfant. Le second récupère les données qui nous intéressent, selon la `DataSource` et les props existantes. -When `CommentListWithSubscription` and `BlogPostWithSubscription` are rendered, `CommentList` and `BlogPost` will be passed a `data` prop with the most current data retrieved from `DataSource`: +Au moment où `CommentListWithSubscription` et `BlogPostWithSubscription` font leur rendu, `CommentList` et `BlogPost` reçoivent une prop `data` qui contient les données les plus récentes de `DataSource`: ```js -// This function takes a component... +// Cette fonction accepte un composant... function withSubscription(WrappedComponent, selectData) { - // ...and returns another component... + // ... et renvoie un autre composant... return class extends React.Component { constructor(props) { super(props); @@ -140,7 +140,7 @@ function withSubscription(WrappedComponent, selectData) { } componentDidMount() { - // ... that takes care of the subscription... + // ... qui s'occupe d'écouter les événements... DataSource.addChangeListener(this.handleChange); } @@ -155,21 +155,21 @@ function withSubscription(WrappedComponent, selectData) { } render() { - // ... and renders the wrapped component with the fresh data! - // Notice that we pass through any additional props + // ... et fait le rendu du composant enfant avec les données à jour! + // Notez qu'on passe aussi toute prop existante return ; } }; } ``` -Note that a HOC doesn't modify the input component, nor does it use inheritance to copy its behavior. Rather, a HOC *composes* the original component by *wrapping* it in a container component. A HOC is a pure function with zero side-effects. +Vous voyez qu'un HOC ne modifie pas le composant qu'on lui passe, ni ni n'hérite et ne copie son comportement. Un HOC *compose* le composant initial en l'*enveloppant* dans un composant conteneur. Il s'agit purement d'une fonction, sans effets secondaires. -And that's it! The wrapped component receives all the props of the container, along with a new prop, `data`, which it uses to render its output. The HOC isn't concerned with how or why the data is used, and the wrapped component isn't concerned with where the data came from. +Et voilà ! Le composant enfant reçoit toutes les props du contenant ainsi qu'une nouvelle prop, `data`, qu'il emploie pour faire son rendu. Le HOC ne se préoccupe pas de comment ou pourquoi les données sont utilisées, et le composant enfant ne se préoccupe pas d'où les données viennent. -Because `withSubscription` is a normal function, you can add as many or as few arguments as you like. For example, you may want to make the name of the `data` prop configurable, to further isolate the HOC from the wrapped component. Or you could accept an argument that configures `shouldComponentUpdate`, or one that configures the data source. These are all possible because the HOC has full control over how the component is defined. +Puisque `withSubscription` est simplement une fonction, vous pouvez lui passer autant ou aussi peu d'arguments que vous voulez. Par exemple, vous pourriez rendre configurable le nom de la prop `data`, afin se séparer encore plus le HOC et son enfant. Ou alors, vous pourriez accepter un argument qui configure `shouldComponentUpdate`, ou un autre qui configure la source de données. Tout cela est possible parce que le HOC a un contrôle total sur la façon dont le composant est défini. -Like components, the contract between `withSubscription` and the wrapped component is entirely props-based. This makes it easy to swap one HOC for a different one, as long as they provide the same props to the wrapped component. This may be useful if you change data-fetching libraries, for example. +Comme pour les composants, le rapport entre `withSubscription` et le composant enfant se base sur les props. Cela facilite l'échange d'un HOC pour un autre, tant qu'ils fournissent les mêmes props au composant enfant. Cela peut être utile si vous changez de bibliothèque pour récupérer vos données, par exemple. ## Don't Mutate the Original Component. Use Composition. {#dont-mutate-the-original-component-use-composition} From 70a6529e6d2bfbab8342312b3efb1962eb93fbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Sun, 10 Mar 2019 13:55:10 +0100 Subject: [PATCH 09/31] Translate "Don't mutate the original component. Use composition." --- content/docs/higher-order-components.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 706256aa8..739b0288f 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -165,15 +165,15 @@ function withSubscription(WrappedComponent, selectData) { Vous voyez qu'un HOC ne modifie pas le composant qu'on lui passe, ni ni n'hérite et ne copie son comportement. Un HOC *compose* le composant initial en l'*enveloppant* dans un composant conteneur. Il s'agit purement d'une fonction, sans effets secondaires. -Et voilà ! Le composant enfant reçoit toutes les props du contenant ainsi qu'une nouvelle prop, `data`, qu'il emploie pour faire son rendu. Le HOC ne se préoccupe pas de comment ou pourquoi les données sont utilisées, et le composant enfant ne se préoccupe pas d'où les données viennent. +Et voilà ! Le composant enfant reçoit toutes les props du conteneur ainsi qu'une nouvelle prop, `data`, qu'il emploie pour faire son rendu. Le HOC ne se préoccupe pas de comment ou pourquoi les données sont utilisées, et le composant enfant ne se préoccupe pas d'où les données viennent. Puisque `withSubscription` est simplement une fonction, vous pouvez lui passer autant ou aussi peu d'arguments que vous voulez. Par exemple, vous pourriez rendre configurable le nom de la prop `data`, afin se séparer encore plus le HOC et son enfant. Ou alors, vous pourriez accepter un argument qui configure `shouldComponentUpdate`, ou un autre qui configure la source de données. Tout cela est possible parce que le HOC a un contrôle total sur la façon dont le composant est défini. Comme pour les composants, le rapport entre `withSubscription` et le composant enfant se base sur les props. Cela facilite l'échange d'un HOC pour un autre, tant qu'ils fournissent les mêmes props au composant enfant. Cela peut être utile si vous changez de bibliothèque pour récupérer vos données, par exemple. -## Don't Mutate the Original Component. Use Composition. {#dont-mutate-the-original-component-use-composition} +## Ne faites pas une mutation du composant initial. Faites une composition. {#dont-mutate-the-original-component-use-composition} -Resist the temptation to modify a component's prototype (or otherwise mutate it) inside a HOC. +Résistez à la tentation de modifier le prototype d'un composant (ou de faire une mutation) dans un HOC. ```js function logProps(InputComponent) { @@ -181,20 +181,19 @@ function logProps(InputComponent) { console.log('Current props: ', this.props); console.log('Next props: ', nextProps); }; - // The fact that we're returning the original input is a hint that it has - // been mutated. + // Le fait que le composant initial soit renvoyé est un signe qu'il a subi une mutation. return InputComponent; } -// EnhancedComponent will log whenever props are received +// EnhancedComponent fera un log à chaque fois qu'il reçoit des props const EnhancedComponent = logProps(InputComponent); ``` -There are a few problems with this. One is that the input component cannot be reused separately from the enhanced component. More crucially, if you apply another HOC to `EnhancedComponent` that *also* mutates `componentWillReceiveProps`, the first HOC's functionality will be overridden! This HOC also won't work with function components, which do not have lifecycle methods. +Cela pose certains problèmes. Pour commencer, le composant initial ne peut pas être réutilisé sans le composant amélioré. Plus important encore, si vous appliquez un autre HOC sur `EnhancedComponent` qui fait *aussi* une mutation de `componentWillReceiveProps`, les fonctionnalités du premier HOC seront écrasées. Finalement, ce HOC ne fonctionnera pas avec des fonctions composants, qui n'ont pas de méthodes de cycle de vie. -Mutating HOCs are a leaky abstraction—the consumer must know how they are implemented in order to avoid conflicts with other HOCs. +La mutation de HOC est une abstraction peu fiable—le client doit savoir comment ils sont implémentés s'il veut éviter des conflits avec d'autres HOC. -Instead of mutation, HOCs should use composition, by wrapping the input component in a container component: +Plutôt que la mutation, les HOC devraient utiliser la composition, en enveloppant le composant initial dans un composant conteneur. ```js function logProps(WrappedComponent) { @@ -204,16 +203,16 @@ function logProps(WrappedComponent) { console.log('Next props: ', nextProps); } render() { - // Wraps the input component in a container, without mutating it. Good! + // Enveloppe le composant initial dans un conteneur, sans faire de mutation. Mieux ! return ; } } } ``` -This HOC has the same functionality as the mutating version while avoiding the potential for clashes. It works equally well with class and function components. And because it's a pure function, it's composable with other HOCs, or even with itself. +Ce HOC a la même fonctionnalité que la version effectuant une mutation, tout en évitant le risque de confits. Il fonctionne tout aussi bien avec les composants à base de classe et les fonctions composants. Et, puisqu'il est tout simplement une fonction, il est compatible avec d'autres HOC et même avec lui-même. -You may have noticed similarities between HOCs and a pattern called **container components**. Container components are part of a strategy of separating responsibility between high-level and low-level concerns. Containers manage things like subscriptions and state, and pass props to components that handle things like rendering UI. HOCs use containers as part of their implementation. You can think of HOCs as parameterized container component definitions. +Vous avez peut-être remarqué des ressemblances entre les HOC et le motif des **composants conteneurs**. Les composants conteneurs participent à la stratégie de séparer les responsabilités entre les préoccupations de haut et de bas niveau. Les conteneurs se préoccupent par exemple des souscriptions et de l'état global, et passent des props à d'autres composants qui se préoccupent par exemple de faire le rendu de l'interface utilisateur. Les HOC utilisent des conteneurs dans leur implémentation. Vous pouvez voir les HOC comme des définitions paramétrées de composants conteneurs. ## Convention: Pass Unrelated Props Through to the Wrapped Component {#convention-pass-unrelated-props-through-to-the-wrapped-component} From 6bb664006104d9c36115f8097808e3fe48692282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Sun, 10 Mar 2019 14:11:02 +0100 Subject: [PATCH 10/31] Translate "Convention: pass unrelated props..." --- content/docs/higher-order-components.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 739b0288f..f9f34c951 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -214,23 +214,21 @@ Ce HOC a la même fonctionnalité que la version effectuant une mutation, tout e Vous avez peut-être remarqué des ressemblances entre les HOC et le motif des **composants conteneurs**. Les composants conteneurs participent à la stratégie de séparer les responsabilités entre les préoccupations de haut et de bas niveau. Les conteneurs se préoccupent par exemple des souscriptions et de l'état global, et passent des props à d'autres composants qui se préoccupent par exemple de faire le rendu de l'interface utilisateur. Les HOC utilisent des conteneurs dans leur implémentation. Vous pouvez voir les HOC comme des définitions paramétrées de composants conteneurs. -## Convention: Pass Unrelated Props Through to the Wrapped Component {#convention-pass-unrelated-props-through-to-the-wrapped-component} +## Convention: transmettez les props sans rapport au composant enfant {#convention-pass-unrelated-props-through-to-the-wrapped-component} -HOCs add features to a component. They shouldn't drastically alter its contract. It's expected that the component returned from a HOC has a similar interface to the wrapped component. +Les HOC ajoutent des fonctionnalités à un composant. Ils ne devraient pas drastiquement modifier son contrat. On s'attend à ce que le composant renvoyé par un HOC aie une interface semblable au composant initial. -HOCs should pass through props that are unrelated to its specific concern. Most HOCs contain a render method that looks something like this: +Les HOC devraient transmettre les props sans rapport avec leurs propres préoccupations. La méthode de rendu de la plupart des HOC ressemble à ceci : ```js render() { - // Filter out extra props that are specific to this HOC and shouldn't be - // passed through + // Filtre les props supplémentaires propres à ce HOC qui ne devraient pas être trasmises const { extraProp, ...passThroughProps } = this.props; - // Inject props into the wrapped component. These are usually state values or - // instance methods. + // Injecte les props dans le composant enfant. Il s'agit en général de valeurs de l'état global ou de méthodes d'instance const injectedProp = someStateOrInstanceMethod; - // Pass props to wrapped component + // Transmet les props au composant enfant return ( Date: Mon, 11 Mar 2019 09:14:00 +0100 Subject: [PATCH 11/31] Translate "Convention: Maximizing Composability" --- content/docs/higher-order-components.md | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index f9f34c951..0452dbda1 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -20,7 +20,7 @@ Dans ce guide, nous verrons pourquoi les composants d'ordre supérieurs sont uti ## Utiliser les HOC pour les préoccupations transversales {#use-hocs-for-cross-cutting-concerns} -> **Note** +> **Remarque** > > Nous recommandions dans le passé d'employer des mixins pour gérer les préoccupations transversales. Depuis, nous nous sommes rendus compte que les mixins créent plus de problèmes qu'ils n'en résolvent. [Lisez-en plus](/blog/2016/07/13/mixins-considered-harmful.html) sur pourquoi nous avons renoncé aux mixins, et comment vous pouvez faire de même pour vos composants existants. @@ -240,57 +240,57 @@ render() { Cette convention participe à garantir que les HOC soient aussi flexibles et réutilisables que possible. -## Convention: Maximizing Composability {#convention-maximizing-composability} +## Convention: maximiser la composabilité {#convention-maximizing-composability} -Not all HOCs look the same. Sometimes they accept only a single argument, the wrapped component: +Tous les HOC ne sont pas pareils. Dans certains cas ils n'acceptent qu'un seul argument, le composant enfant : ```js const NavbarWithRouter = withRouter(Navbar); ``` -Usually, HOCs accept additional arguments. In this example from Relay, a config object is used to specify a component's data dependencies: +Mais en général, les HOC acceptent des arguments supplémentires. Dans cet exemple tiré de Relay, un objet de configuration `config` est transmis pour spécifier les dépendances d'un composant à des données : ```js const CommentWithRelay = Relay.createContainer(Comment, config); ``` -The most common signature for HOCs looks like this: +La signature la plus commune des HOC ressemble à ceci : ```js -// React Redux's `connect` +// `connect` de React Redux const ConnectedComment = connect(commentSelector, commentActions)(CommentList); ``` -*What?!* If you break it apart, it's easier to see what's going on. +*Pardon ?!* Il est plus facile de voir ce qu'il se passe si on le sépare en plusieurs morceaux. ```js -// connect is a function that returns another function +// connect est une fonction qui renvoie une autre function const enhance = connect(commentListSelector, commentListActions); -// The returned function is a HOC, which returns a component that is connected -// to the Redux store +// La fonction renvoyée est un HOC, qui renvoie un composant connecté au store Redux const ConnectedComment = enhance(CommentList); ``` -In other words, `connect` is a higher-order function that returns a higher-order component! -This form may seem confusing or unnecessary, but it has a useful property. Single-argument HOCs like the one returned by the `connect` function have the signature `Component => Component`. Functions whose output type is the same as its input type are really easy to compose together. +Autrement dit, `connect` est une fonction d'ordre supérieur qui renvoie un composant d'ordre supérieur ! + +Cette structure peut sembler déroutante ou superflue, pourtant elle apporte une propriété utile. Les HOC n'acceptant qu'un argument comme celui que renvoie la fonction `connect` ont une signature `Composant => Composant`. Les fonctions dont le type de données est le même à la sortie qu'à l'entrée sont beaucoup plus facile à composer. ```js -// Instead of doing this... +// Plutôt que de faire ceci... const EnhancedComponent = withRouter(connect(commentSelector)(WrappedComponent)) -// ... you can use a function composition utility -// compose(f, g, h) is the same as (...args) => f(g(h(...args))) +// ... vous pouvez utiliser un utilitaire de composition de fonction +// compose(f, g, h) est l'équivalent de (...args) => f(g(h(...args))) const enhance = compose( - // These are both single-argument HOCs + // Ceux-ci sont tous deux des HOC n'acceptant qu'un argument withRouter, connect(commentSelector) ) const EnhancedComponent = enhance(WrappedComponent) ``` -(This same property also allows `connect` and other enhancer-style HOCs to be used as decorators, an experimental JavaScript proposal.) +(C'est aussi cette propriété qui permet à `connect` et à d'autres HOC du même type d'être utilisés comme décorateurs, une proposition expérimentale JavaScript) -The `compose` utility function is provided by many third-party libraries including lodash (as [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose), and [Ramda](https://ramdajs.com/docs/#compose). +La fonction utilitaire `compose` est offerte par de nombreuses bibliothèqes tierces, y compris lodash (nommée [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose), et [Ramda](https://ramdajs.com/docs/#compose). ## Convention: Wrap the Display Name for Easy Debugging {#convention-wrap-the-display-name-for-easy-debugging} From 13817defc725680949fe4c641ba6b84cd94c40c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Mon, 11 Mar 2019 09:15:56 +0100 Subject: [PATCH 12/31] Rename heading --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 0452dbda1..9855f7cfa 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -171,7 +171,7 @@ Puisque `withSubscription` est simplement une fonction, vous pouvez lui passer a Comme pour les composants, le rapport entre `withSubscription` et le composant enfant se base sur les props. Cela facilite l'échange d'un HOC pour un autre, tant qu'ils fournissent les mêmes props au composant enfant. Cela peut être utile si vous changez de bibliothèque pour récupérer vos données, par exemple. -## Ne faites pas une mutation du composant initial. Faites une composition. {#dont-mutate-the-original-component-use-composition} +## Ne modifiez pas le composant initial. Composez-le. {#dont-mutate-the-original-component-use-composition} Résistez à la tentation de modifier le prototype d'un composant (ou de faire une mutation) dans un HOC. From a18edd5102063ab88e8667ab1408ad8d7e25d032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Mon, 11 Mar 2019 09:27:28 +0100 Subject: [PATCH 13/31] Translate "Convention: Wrap the Display Name..." --- content/docs/higher-order-components.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 9855f7cfa..1e8609278 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -292,11 +292,11 @@ const EnhancedComponent = enhance(WrappedComponent) La fonction utilitaire `compose` est offerte par de nombreuses bibliothèqes tierces, y compris lodash (nommée [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose), et [Ramda](https://ramdajs.com/docs/#compose). -## Convention: Wrap the Display Name for Easy Debugging {#convention-wrap-the-display-name-for-easy-debugging} +## Convention: enveloppez le nom d'affichage pour faciliter le débogage {#convention-wrap-the-display-name-for-easy-debugging} -The container components created by HOCs show up in the [React Developer Tools](https://github.com/facebook/react-devtools) like any other component. To ease debugging, choose a display name that communicates that it's the result of a HOC. +Tout comme n'importe quel autre composant, les composants conteneurs créés par des HOC apparaîssent dans les [Outils de développement React](https://github.com/facebook/react-devtools). Pour faciliter votre débogage, donnez-leur un nom d'affichage qui signifie qu'ils ont été crées par des HOC. -The most common technique is to wrap the display name of the wrapped component. So if your higher-order component is named `withSubscription`, and the wrapped component's display name is `CommentList`, use the display name `WithSubscription(CommentList)`: +Le technique ls plus commune est d'envelopper le nom d'affichage du composant enfant. Par exemple, si votre composant d'ordre supérieur s'appelle `withSubscription`, et que le nom d'affichage du composant enfant est `CommentList`, utilisez le nom d'affichage `WithSubscription(CommentList)` : ```js function withSubscription(WrappedComponent) { From d876b89c30323f22e9878f3e89ec86fdad0062ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Mon, 11 Mar 2019 09:28:00 +0100 Subject: [PATCH 14/31] Use imperative to harmonize Convention headings --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 1e8609278..fa3d6a8e4 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -240,7 +240,7 @@ render() { Cette convention participe à garantir que les HOC soient aussi flexibles et réutilisables que possible. -## Convention: maximiser la composabilité {#convention-maximizing-composability} +## Convention: maximisez la composabilité {#convention-maximizing-composability} Tous les HOC ne sont pas pareils. Dans certains cas ils n'acceptent qu'un seul argument, le composant enfant : From b687ddf3328741220348d5d5c4e9079d87359f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Mon, 11 Mar 2019 09:35:57 +0100 Subject: [PATCH 15/31] Translate "Caveats" intro --- content/docs/higher-order-components.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index fa3d6a8e4..5918c675a 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -311,9 +311,9 @@ function getDisplayName(WrappedComponent) { ``` -## Caveats {#caveats} +## Avertissements {#caveats} -Higher-order components come with a few caveats that aren't immediately obvious if you're new to React. +L'utilisation de composants d'ordre supérieur comporte quelques risques qui ne seront pas tout de suite évidents si vous débutez avec React. ### Don't Use HOCs Inside the render Method {#dont-use-hocs-inside-the-render-method} From 21fb253648e1210f6669986c6415cf99664079f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Mon, 11 Mar 2019 14:13:12 +0100 Subject: [PATCH 16/31] Translate "Don't Use HOCs Inside the Render Method" --- content/docs/higher-order-components.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 5918c675a..5fc54c030 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -315,27 +315,27 @@ function getDisplayName(WrappedComponent) { L'utilisation de composants d'ordre supérieur comporte quelques risques qui ne seront pas tout de suite évidents si vous débutez avec React. -### Don't Use HOCs Inside the render Method {#dont-use-hocs-inside-the-render-method} +### Pas de HOC à l'intérieur de la méthode de rendu {#dont-use-hocs-inside-the-render-method} -React's diffing algorithm (called reconciliation) uses component identity to determine whether it should update the existing subtree or throw it away and mount a new one. If the component returned from `render` is identical (`===`) to the component from the previous render, React recursively updates the subtree by diffing it with the new one. If they're not equal, the previous subtree is unmounted completely. +L'algorithme de différentiation de React (qu'on appelle réconcilation) utilise l'identité des composants pour déterminer s'il faut mettre à jour l'arborescence existante ou en monter une nouvelle. Si le composant renvoyé par `render` est identique (`===`) au composant du rendu précédent, React met à jour l'ancienne arborescence en la différenciant résursivement avec la nouvelle. S'ils ne sont pas identiques, l'ancienne arborescence est intégralement démontée. -Normally, you shouldn't need to think about this. But it matters for HOCs because it means you can't apply a HOC to a component within the render method of a component: +En général, vous ne devriez pas avoir à y penser. Mais dans le cadre des HOC, cela importe puisque cela signifie que vous ne pouvez pas utiliser un HOC au sein de la méthode de rendu d'un composant : ```js render() { - // A new version of EnhancedComponent is created on every render + // Une nouvelle version de EnhancedComponent est créée à chaque rendu // EnhancedComponent1 !== EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); - // That causes the entire subtree to unmount/remount each time! + // Cela cause le démontage et remontage de toute l'arborescence à chaque fois ! return ; } ``` -The problem here isn't just about performance — remounting a component causes the state of that component and all of its children to be lost. +Il ne s'agit pas uniquement d'un problème de performance—remonter un composant signifie que l'état local de ce composant ainsi que celui de tous ses enfants sera perdu. -Instead, apply HOCs outside the component definition so that the resulting component is created only once. Then, its identity will be consistent across renders. This is usually what you want, anyway. +Utilisez plutôt les HOC à l'extérieur de la définition d'un composant, afin de créer le composant final une seule fois. Son identité sera alors constante lors des rendus. C'est normalement ce que vous voulez, non ? -In those rare cases where you need to apply a HOC dynamically, you can also do it inside a component's lifecycle methods or its constructor. +Dans les rares cas où vous devriez utiliser un HOC de façon dynamique, vous pouvez le faire au sein des méthodes de cycle de vie d'un composant ou dans son contructeur. ### Static Methods Must Be Copied Over {#static-methods-must-be-copied-over} From 5d65b084cfe82cb938df1f9c8d4ee57b7cbc3ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Mon, 11 Mar 2019 14:28:44 +0100 Subject: [PATCH 17/31] Translate "Static Methods Must be Copied Over" --- content/docs/higher-order-components.md | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 5fc54c030..07d94ca9c 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -337,34 +337,34 @@ Utilisez plutôt les HOC à l'extérieur de la définition d'un composant, afin Dans les rares cas où vous devriez utiliser un HOC de façon dynamique, vous pouvez le faire au sein des méthodes de cycle de vie d'un composant ou dans son contructeur. -### Static Methods Must Be Copied Over {#static-methods-must-be-copied-over} +### Les méthodes statiques doivent être copiées {#static-methods-must-be-copied-over} -Sometimes it's useful to define a static method on a React component. For example, Relay containers expose a static method `getFragment` to facilitate the composition of GraphQL fragments. +Il est parfois utile de définir une méthode statique dans un composant React. Par exemple, les conteneurs Relay exposent une méthode statique `getFragment` pour simplifier la composition de fragments GraphQL. -When you apply a HOC to a component, though, the original component is wrapped with a container component. That means the new component does not have any of the static methods of the original component. +Cependant, quand vous appliquez un HOC à un composant, le composant initial est enveloppé par un composant conteneur. Cela signifie que le nouveau composant ne comporte aucune des méthodes statiques du composant initial. ```js -// Define a static method +// Définit une méthode statique WrappedComponent.staticMethod = function() {/*...*/} -// Now apply a HOC +// Applique un HOC const EnhancedComponent = enhance(WrappedComponent); -// The enhanced component has no static method +// Le composant amélioré n'a pas de méthode statique typeof EnhancedComponent.staticMethod === 'undefined' // true ``` -To solve this, you could copy the methods onto the container before returning it: +Pour résoudre cela, vous pouvez copier les méthodes dans le conteneur avant de le renvoyer : ```js function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} - // Must know exactly which method(s) to copy :( + // Doit connaître exactement quelles méthodes recopier :( Enhance.staticMethod = WrappedComponent.staticMethod; return Enhance; } ``` -However, this requires you to know exactly which methods need to be copied. You can use [hoist-non-react-statics](https://github.com/mridgway/hoist-non-react-statics) to automatically copy all non-React static methods: +Par contre, cela exige que vous sachiez exactement quelles méthodes doivent être copiées. Vous pouvez autrement utiliser [hoist-non-react-statics](https://github.com/mridgway/hoist-non-react-statics) qui copie automatiquement toutes les méthodes statiques : ```js import hoistNonReactStatic from 'hoist-non-react-statics'; @@ -375,17 +375,17 @@ function enhance(WrappedComponent) { } ``` -Another possible solution is to export the static method separately from the component itself. +Une autre solution est d'exporter les méthodes statiques séparées du composant lui-même. ```js -// Instead of... +// Plutôt que... MyComponent.someFunction = someFunction; export default MyComponent; -// ...export the method separately... +// ... exportez les méthodes séparées du composant... export { someFunction }; -// ...and in the consuming module, import both +// ... et dans le module qui les utilise, importez les deux import MyComponent, { someFunction } from './MyComponent.js'; ``` From 73f383a8e3a6fc362520e5609527c4454f8a30c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Mon, 11 Mar 2019 14:29:56 +0100 Subject: [PATCH 18/31] Switch utiliser to appliquer --- content/docs/higher-order-components.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 07d94ca9c..7430f567d 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -319,7 +319,7 @@ L'utilisation de composants d'ordre supérieur comporte quelques risques qui ne L'algorithme de différentiation de React (qu'on appelle réconcilation) utilise l'identité des composants pour déterminer s'il faut mettre à jour l'arborescence existante ou en monter une nouvelle. Si le composant renvoyé par `render` est identique (`===`) au composant du rendu précédent, React met à jour l'ancienne arborescence en la différenciant résursivement avec la nouvelle. S'ils ne sont pas identiques, l'ancienne arborescence est intégralement démontée. -En général, vous ne devriez pas avoir à y penser. Mais dans le cadre des HOC, cela importe puisque cela signifie que vous ne pouvez pas utiliser un HOC au sein de la méthode de rendu d'un composant : +En général, vous ne devriez pas avoir à y penser. Mais dans le cadre des HOC, cela importe puisque cela signifie que vous ne pouvez pas appliquer un HOC au sein de la méthode de rendu d'un composant : ```js render() { @@ -333,9 +333,9 @@ render() { Il ne s'agit pas uniquement d'un problème de performance—remonter un composant signifie que l'état local de ce composant ainsi que celui de tous ses enfants sera perdu. -Utilisez plutôt les HOC à l'extérieur de la définition d'un composant, afin de créer le composant final une seule fois. Son identité sera alors constante lors des rendus. C'est normalement ce que vous voulez, non ? +Appliquez plutôt les HOC à l'extérieur de la définition d'un composant, afin de créer le composant final une seule fois. Son identité sera alors constante lors des rendus. C'est normalement ce que vous voulez, non ? -Dans les rares cas où vous devriez utiliser un HOC de façon dynamique, vous pouvez le faire au sein des méthodes de cycle de vie d'un composant ou dans son contructeur. +Dans les rares cas où vous devriez appliquer un HOC de façon dynamique, vous pouvez le faire au sein des méthodes de cycle de vie d'un composant ou dans son contructeur. ### Les méthodes statiques doivent être copiées {#static-methods-must-be-copied-over} From 67fada5ec0b1d4822f6b97c084d5bbc54b9dd87e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Mon, 11 Mar 2019 14:38:24 +0100 Subject: [PATCH 19/31] Translate "Refs aren't Passed Through" --- content/docs/higher-order-components.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 7430f567d..3008ec5c0 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -389,8 +389,8 @@ export { someFunction }; import MyComponent, { someFunction } from './MyComponent.js'; ``` -### Refs Aren't Passed Through {#refs-arent-passed-through} +### Ne transmettez pas les refs {#refs-arent-passed-through} -While the convention for higher-order components is to pass through all props to the wrapped component, this does not work for refs. That's because `ref` is not really a prop — like `key`, it's handled specially by React. If you add a ref to an element whose component is the result of a HOC, the ref refers to an instance of the outermost container component, not the wrapped component. +Bien que que la convention pour les composants d'ordre supérieur soit de transmettre toutes les props au composant enfant, elle ne s'applique pas aux refs. Une `ref` n'est en effet pas vraiment une prop—comme une `key`, React la traite de façon particulière. Si vous ajoutez une ref à un élément dont le composant résulte d'un HOC, la ref fait référence à une instance du composant conteneur le plus à l'extérieur, et non pas au composant enfant. -The solution for this problem is to use the `React.forwardRef` API (introduced with React 16.3). [Learn more about it in the forwarding refs section](/docs/forwarding-refs.html). +La solution à ce problème réside dans l'utilisation de l'API `React.forwardRef` (introduite dans React 16.3). [Apprenez-en plus dans la section sur la transmission des refs](/docs/forwarding-refs.html). From 938c8256eb0e8e995b25e3f8056b69f55023f022 Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 15:05:18 +0100 Subject: [PATCH 20/31] Update content/docs/higher-order-components.md Co-Authored-By: robinmetral <35560568+robinmetral@users.noreply.github.com> --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 3008ec5c0..38dcad399 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -4,7 +4,7 @@ title: Composants d'ordre supérieur permalink: docs/higher-order-components.html --- -Un composant d'ordre supérieur (HOC) est une technique avancée de React qui permet de réutiliser la logique de composants. Les HOC ne font pas partie de l'API de React en soi, mais émergent de la nature compositionnelle de React. +Un composant d'ordre supérieur *(Higher-Order Component ou HOC, NdT)* est une technique avancée de React qui permet de réutiliser la logique de composants. Les HOC ne font pas partie de l'API de React à proprement parler, mais découlent de la nature compositionnelle de React. Concrètement, **un composant d'ordre supérieur est une fonction qui accepte un composant et renvoie un nouveau composant.** From a6f70b97145437383d418a272df663528346b478 Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 15:08:06 +0100 Subject: [PATCH 21/31] Update content/docs/higher-order-components.md Co-Authored-By: robinmetral <35560568+robinmetral@users.noreply.github.com> --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 38dcad399..6d5fc16f7 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -22,7 +22,7 @@ Dans ce guide, nous verrons pourquoi les composants d'ordre supérieurs sont uti > **Remarque** > -> Nous recommandions dans le passé d'employer des mixins pour gérer les préoccupations transversales. Depuis, nous nous sommes rendus compte que les mixins créent plus de problèmes qu'ils n'en résolvent. [Lisez-en plus](/blog/2016/07/13/mixins-considered-harmful.html) sur pourquoi nous avons renoncé aux mixins, et comment vous pouvez faire de même pour vos composants existants. +> Auparavant, nous recommandions d'employer des *mixins* pour gérer les questions transversales. Depuis, nous nous sommes rendus compte que les *mixins* créent plus de problèmes qu'ils n'en résolvent. Vous pouvez [lire le détail](/blog/2016/07/13/mixins-considered-harmful.html) des raisons qui nous ont fait renoncer aux *mixins*, et de la façon dont vous pouvez faire de même pour vos composants existants. Les composants React constituent le moyen le plus primaire de réutiliser du code. Cependant, vous remarquerez que les composants classiques ne conviennent pas à tous les modèles. From 53cda20bbb64b7343aeec43cdda90f7cc1ed07ba Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 15:09:31 +0100 Subject: [PATCH 22/31] Update content/docs/higher-order-components.md Co-Authored-By: robinmetral <35560568+robinmetral@users.noreply.github.com> --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 6d5fc16f7..865a380f6 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -12,7 +12,7 @@ Concrètement, **un composant d'ordre supérieur est une fonction qui accepte un const EnhancedComponent = higherOrderComponent(WrappedComponent); ``` -Là où un composant transforme des props en interface utilisateur, un composant d'ordre supérieur transforme un composant en un autre composant. +Là où un composant transforme des props en interface utilisateur (UI), un composant d'ordre supérieur transforme un composant en un autre composant. Les HOC sont courants dans des bibliothèques tierces de React, comme [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) dans Redux et [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) dans Relay. From 76469c719bc175609776cf7e8816ae006477325f Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 15:09:45 +0100 Subject: [PATCH 23/31] Update content/docs/higher-order-components.md Co-Authored-By: robinmetral <35560568+robinmetral@users.noreply.github.com> --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 865a380f6..ca2d4515e 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -18,7 +18,7 @@ Les HOC sont courants dans des bibliothèques tierces de React, comme [`connect` Dans ce guide, nous verrons pourquoi les composants d'ordre supérieurs sont utiles, et comment créer le vôtre. -## Utiliser les HOC pour les préoccupations transversales {#use-hocs-for-cross-cutting-concerns} +## Utiliser les HOC pour les questions transversales {#use-hocs-for-cross-cutting-concerns} > **Remarque** > From dac63c3b938bd50ca21c971e6a1ea1a222932100 Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 15:09:57 +0100 Subject: [PATCH 24/31] Update content/docs/higher-order-components.md Co-Authored-By: robinmetral <35560568+robinmetral@users.noreply.github.com> --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index ca2d4515e..d3517f6df 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -20,7 +20,7 @@ Dans ce guide, nous verrons pourquoi les composants d'ordre supérieurs sont uti ## Utiliser les HOC pour les questions transversales {#use-hocs-for-cross-cutting-concerns} -> **Remarque** +> Remarque > > Auparavant, nous recommandions d'employer des *mixins* pour gérer les questions transversales. Depuis, nous nous sommes rendus compte que les *mixins* créent plus de problèmes qu'ils n'en résolvent. Vous pouvez [lire le détail](/blog/2016/07/13/mixins-considered-harmful.html) des raisons qui nous ont fait renoncer aux *mixins*, et de la façon dont vous pouvez faire de même pour vos composants existants. From dbaee1da739c3a88b95f5f63cdec753755312fcb Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 15:10:14 +0100 Subject: [PATCH 25/31] Update content/docs/higher-order-components.md Co-Authored-By: robinmetral <35560568+robinmetral@users.noreply.github.com> --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index d3517f6df..20e6bdc09 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -375,7 +375,7 @@ function enhance(WrappedComponent) { } ``` -Une autre solution est d'exporter les méthodes statiques séparées du composant lui-même. +Une autre solution consiste à exporter les méthodes statiques séparément du composant lui-même. ```js // Plutôt que... From 41f3d147795696c3a63fa560d25bb81780e0b3ab Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 15:10:31 +0100 Subject: [PATCH 26/31] Update content/docs/higher-order-components.md Co-Authored-By: robinmetral <35560568+robinmetral@users.noreply.github.com> --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 20e6bdc09..fb83ab1e3 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -382,7 +382,7 @@ Une autre solution consiste à exporter les méthodes statiques séparément du MyComponent.someFunction = someFunction; export default MyComponent; -// ... exportez les méthodes séparées du composant... +// ... exportez les méthodes séparément... export { someFunction }; // ... et dans le module qui les utilise, importez les deux From fc4941e038c36d74bebf00e5012122aeeede126d Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 15:10:44 +0100 Subject: [PATCH 27/31] Update content/docs/higher-order-components.md Co-Authored-By: robinmetral <35560568+robinmetral@users.noreply.github.com> --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index fb83ab1e3..13ce0d454 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -389,7 +389,7 @@ export { someFunction }; import MyComponent, { someFunction } from './MyComponent.js'; ``` -### Ne transmettez pas les refs {#refs-arent-passed-through} +### Les refs ne sont pas transmises {#refs-arent-passed-through} Bien que que la convention pour les composants d'ordre supérieur soit de transmettre toutes les props au composant enfant, elle ne s'applique pas aux refs. Une `ref` n'est en effet pas vraiment une prop—comme une `key`, React la traite de façon particulière. Si vous ajoutez une ref à un élément dont le composant résulte d'un HOC, la ref fait référence à une instance du composant conteneur le plus à l'extérieur, et non pas au composant enfant. From 95eb13262855cff6d5c49eb2b9fdd7caefe0078c Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 15:11:07 +0100 Subject: [PATCH 28/31] Update content/docs/higher-order-components.md Co-Authored-By: robinmetral <35560568+robinmetral@users.noreply.github.com> --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 13ce0d454..687afd18e 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -393,4 +393,4 @@ import MyComponent, { someFunction } from './MyComponent.js'; Bien que que la convention pour les composants d'ordre supérieur soit de transmettre toutes les props au composant enfant, elle ne s'applique pas aux refs. Une `ref` n'est en effet pas vraiment une prop—comme une `key`, React la traite de façon particulière. Si vous ajoutez une ref à un élément dont le composant résulte d'un HOC, la ref fait référence à une instance du composant conteneur le plus à l'extérieur, et non pas au composant enfant. -La solution à ce problème réside dans l'utilisation de l'API `React.forwardRef` (introduite dans React 16.3). [Apprenez-en plus dans la section sur la transmission des refs](/docs/forwarding-refs.html). +La solution à ce problème réside dans l'utilisation de l'API `React.forwardRef` (introduite dans React 16.3). [Apprenez-en davantage dans la section sur la transmission des refs](/docs/forwarding-refs.html). From 98b4665eb87e9119d17a4ee8b7d03459089b6053 Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 15:37:30 +0100 Subject: [PATCH 29/31] Apply suggestions from code review Co-Authored-By: robinmetral <35560568+robinmetral@users.noreply.github.com> --- content/docs/higher-order-components.md | 119 ++++++++++++------------ 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 687afd18e..23e691524 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -24,9 +24,9 @@ Dans ce guide, nous verrons pourquoi les composants d'ordre supérieurs sont uti > > Auparavant, nous recommandions d'employer des *mixins* pour gérer les questions transversales. Depuis, nous nous sommes rendus compte que les *mixins* créent plus de problèmes qu'ils n'en résolvent. Vous pouvez [lire le détail](/blog/2016/07/13/mixins-considered-harmful.html) des raisons qui nous ont fait renoncer aux *mixins*, et de la façon dont vous pouvez faire de même pour vos composants existants. -Les composants React constituent le moyen le plus primaire de réutiliser du code. Cependant, vous remarquerez que les composants classiques ne conviennent pas à tous les modèles. +Les composants sont le principal moyen de réutiliser du code en React. Cependant, vous remarquerez que les composants classiques ne conviennent pas à tous les modèles. -Imaginez que vous ayez créé un composant `CommentList` qui écoute une source externe de données pour faire le rendu d'une liste de commentaires : +Imaginez que vous ayez créé un composant `CommentList` qui écoute une source externe de données pour afficher une liste de commentaires : ```js class CommentList extends React.Component { @@ -40,12 +40,12 @@ class CommentList extends React.Component { } componentDidMount() { - // Crée un écouteur d'événement + // On s'abonne aux modifications DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { - // Nettoie l'écouteur d'événement + // On se désabonne DataSource.removeChangeListener(this.handleChange); } @@ -68,7 +68,7 @@ class CommentList extends React.Component { } ``` -Ensuite, vous créez un composant `BlogPost` qui gère les événements pour un unique article, et dont la structure est similaire à la précédente : +Plus tard, vous créez un composant `BlogPost` qui s'abonne à un unique article, et dont la structure est similaire : ```js class BlogPost extends React.Component { @@ -100,15 +100,15 @@ class BlogPost extends React.Component { } ``` -`CommentList` et `BlogPost` ne sont pas identiques—ils appellent des méthodes différentes sur `DataSource`, et font différents rendus. Pourtant une grande partie de leur fonctionnement est la même: +`CommentList` et `BlogPost` ne sont pas identiques : ils appellent des méthodes différentes sur `DataSource`, et ont des affichages distincts. Pourtant une grande partie de leur implémentation est la même : -- Au montage *(quand le composant entre dans la couche d'affichage, NdT)*, ils ajoutent un écouteur d'événement à `DataSource`. +- Au montage *(quand le composant entre dans la couche d'affichage, NdT)*, ils ajoutent un écouteur d'événements à `DataSource`. - Dans l'écouteur, ils appellent `setState` quand la source de données est modifiée. -- Au démontage *(quand le composant sort de la couche d'affichage, NdT)*, ils enlèvent l'écouteur d'événement. +- Au démontage *(quand le composant sort de la couche d'affichage, NdT)*, ils enlèvent l'écouteur d'événements. -Vous imaginez bien que dans une appli importante, ce motif d'écoute de `DataSource` et d'appel à `setState` sera récurrent. Il nous faut une abstraction qui nous permette de définir cette logique à un seul endroit et de la partager parmi de nombreux composants. C'est là que les composants d'ordre supérieur entrent en jeu. +Vous imaginez bien que dans une appli importante, ce motif d'abonnement à une `DataSource` et d'appel à `setState` sera récurrent. Il nous faut une abstraction qui nous permette de définir cette logique à un seul endroit et de la réutiliser pour de nombreux composants. C'est là que les composants d'ordre supérieur sont particulièrement utiles. -Vous pouvez donc écrire une fonction pour créer des composants qui écoutent `DataSource`, comme `CommentList` et `BlogPost`. L'un des arguments qu'accepte la fonction est un composant enfant, qui recevra les données écoutées en props. Appelons cette fonction `withSubscription`: +Nous pouvons écrire une fonction qui crée des composants qui s'abonnent à une `DataSource`, comme `CommentList` et `BlogPost`. La fonction acceptera parmi ses arguments un composant enfant, qui recevra les données suivies en props. Appelons cette fonction `withSubscription` : ```js const CommentListWithSubscription = withSubscription( @@ -122,9 +122,9 @@ const BlogPostWithSubscription = withSubscription( ); ``` -Le premier paramètre est le composant enfant. Le second récupère les données qui nous intéressent, selon la `DataSource` et les props existantes. +Le premier paramètre est le composant enfant. Le second récupère les données qui nous intéressent, en fonction de la `DataSource` et des props existantes. -Au moment où `CommentListWithSubscription` et `BlogPostWithSubscription` font leur rendu, `CommentList` et `BlogPost` reçoivent une prop `data` qui contient les données les plus récentes de `DataSource`: +Lorsque `CommentListWithSubscription` et `BlogPostWithSubscription` s'affichent, `CommentList` et `BlogPost` reçoivent une prop `data` qui contient les données les plus récentes issues de la `DataSource` : ```js // Cette fonction accepte un composant... @@ -140,7 +140,7 @@ function withSubscription(WrappedComponent, selectData) { } componentDidMount() { - // ... qui s'occupe d'écouter les événements... + // ... qui s'occupe de l'abonnement... DataSource.addChangeListener(this.handleChange); } @@ -155,25 +155,25 @@ function withSubscription(WrappedComponent, selectData) { } render() { - // ... et fait le rendu du composant enfant avec les données à jour! - // Notez qu'on passe aussi toute prop existante + // ... et affiche composant enfant avec les données à jour ! + // Remarquez qu'on passe aussi toute autre prop reçue return ; } }; } ``` -Vous voyez qu'un HOC ne modifie pas le composant qu'on lui passe, ni ni n'hérite et ne copie son comportement. Un HOC *compose* le composant initial en l'*enveloppant* dans un composant conteneur. Il s'agit purement d'une fonction, sans effets secondaires. +Remarquez qu'un HOC ne modifie pas le composant qu'on lui passe, et ne recourt pas non plus à l’héritage pour copier son comportement. Un HOC *compose* le composant initial en l'*enrobant* dans un composant conteneur. Il s'agit d'une fonction pure, sans effets de bord. -Et voilà ! Le composant enfant reçoit toutes les props du conteneur ainsi qu'une nouvelle prop, `data`, qu'il emploie pour faire son rendu. Le HOC ne se préoccupe pas de comment ou pourquoi les données sont utilisées, et le composant enfant ne se préoccupe pas d'où les données viennent. +Et voilà ! Le composant enfant reçoit toutes les props du conteneur ainsi qu'une nouvelle prop, `data`, qu'il emploie pour produire son résultat. Le HOC ne se préoccupe pas de savoir comment ou pourquoi les données sont utilisées, et le composant enfant ne se préoccupe pas de savoir d'où les données viennent. -Puisque `withSubscription` est simplement une fonction, vous pouvez lui passer autant ou aussi peu d'arguments que vous voulez. Par exemple, vous pourriez rendre configurable le nom de la prop `data`, afin se séparer encore plus le HOC et son enfant. Ou alors, vous pourriez accepter un argument qui configure `shouldComponentUpdate`, ou un autre qui configure la source de données. Tout cela est possible parce que le HOC a un contrôle total sur la façon dont le composant est défini. +Puisque `withSubscription` est juste une fonction, vous pouvez lui définir autant ou aussi peu de paramètres que vous le souhaitez. Par exemple, vous pourriez rendre configurable le nom de la prop `data`, afin d’isoler encore davantage le HOC et le composant enrobé. Ou alors, vous pourriez accepter un argument qui configure `shouldComponentUpdate`, ou un autre qui configure la source de données. Tout ça est possible parce que le HOC a un contrôle total sur la façon dont le composant est défini. -Comme pour les composants, le rapport entre `withSubscription` et le composant enfant se base sur les props. Cela facilite l'échange d'un HOC pour un autre, tant qu'ils fournissent les mêmes props au composant enfant. Cela peut être utile si vous changez de bibliothèque pour récupérer vos données, par exemple. +Comme pour les composants, le rapport entre `withSubscription` et le composant enrobé se base entièrement sur les props. Ça facilite l'échange d'un HOC pour un autre, du moment qu'ils fournissent les mêmes props au composant enrobé. Ça peut s'avérer utile si vous changez de bibliothèque pour récupérer vos données, par exemple. ## Ne modifiez pas le composant initial. Composez-le. {#dont-mutate-the-original-component-use-composition} -Résistez à la tentation de modifier le prototype d'un composant (ou de faire une mutation) dans un HOC. +Résistez à la tentation de modifier le prototype d'un composant (ou de le modifier de quelque façon que ce soit) dans un HOC. ```js function logProps(InputComponent) { @@ -181,7 +181,7 @@ function logProps(InputComponent) { console.log('Current props: ', this.props); console.log('Next props: ', nextProps); }; - // Le fait que le composant initial soit renvoyé est un signe qu'il a subi une mutation. + // Le fait que le composant initial soit renvoyé est un signe qu'il a été modifié. return InputComponent; } @@ -189,11 +189,11 @@ function logProps(InputComponent) { const EnhancedComponent = logProps(InputComponent); ``` -Cela pose certains problèmes. Pour commencer, le composant initial ne peut pas être réutilisé sans le composant amélioré. Plus important encore, si vous appliquez un autre HOC sur `EnhancedComponent` qui fait *aussi* une mutation de `componentWillReceiveProps`, les fonctionnalités du premier HOC seront écrasées. Finalement, ce HOC ne fonctionnera pas avec des fonctions composants, qui n'ont pas de méthodes de cycle de vie. +Ce genre d'approche pose quelques problèmes. Pour commencer, le composant initial ne peut pas être réutilisé indépendamment du composant amélioré. Plus important encore, si vous appliquez un autre HOC sur `EnhancedComponent` qui modifie *aussi* `componentWillReceiveProps`, les fonctionnalités du premier HOC seront perdues ! Enfin, ce HOC ne fonctionnera pas avec des fonctions composants, qui n'ont pas de méthodes de cycle de vie. -La mutation de HOC est une abstraction peu fiable—le client doit savoir comment ils sont implémentés s'il veut éviter des conflits avec d'autres HOC. +Les HOC qui modifient le composant enrobé sont une abstraction foireuse : leurs utilisateurs doivent savoir comment ils sont implémentés afin d’éviter des conflits avec d'autres HOC. -Plutôt que la mutation, les HOC devraient utiliser la composition, en enveloppant le composant initial dans un composant conteneur. +Plutôt que la mutation, les HOC devraient utiliser la composition, en enrobant le composant initial dans un composant conteneur. ```js function logProps(WrappedComponent) { @@ -203,32 +203,33 @@ function logProps(WrappedComponent) { console.log('Next props: ', nextProps); } render() { - // Enveloppe le composant initial dans un conteneur, sans faire de mutation. Mieux ! + // Enrobe le composant initial dans un conteneur, sans le modifier. C’est mieux ! return ; } } } ``` -Ce HOC a la même fonctionnalité que la version effectuant une mutation, tout en évitant le risque de confits. Il fonctionne tout aussi bien avec les composants à base de classe et les fonctions composants. Et, puisqu'il est tout simplement une fonction, il est compatible avec d'autres HOC et même avec lui-même. +Ce HOC a la même fonctionnalité que la version modifiante, tout en évitant le risque de confits. Il fonctionne tout aussi bien avec les composants à base de classe et les fonctions composants. Et puisqu'il s'agit d'une fonction pure, il est composable avec d'autres HOC voire même avec lui-même. -Vous avez peut-être remarqué des ressemblances entre les HOC et le motif des **composants conteneurs**. Les composants conteneurs participent à la stratégie de séparer les responsabilités entre les préoccupations de haut et de bas niveau. Les conteneurs se préoccupent par exemple des souscriptions et de l'état global, et passent des props à d'autres composants qui se préoccupent par exemple de faire le rendu de l'interface utilisateur. Les HOC utilisent des conteneurs dans leur implémentation. Vous pouvez voir les HOC comme des définitions paramétrées de composants conteneurs. +Vous avez peut-être remarqué des ressemblances entre les HOC et le motif des **composants conteneurs**. Les composants conteneurs participent à des stratégies de séparation de responsabilités entre les préoccupations de haut et de bas niveau. Les conteneurs se préoccupent par exemple des abonnements et de l'état, et passent des props à d'autres composants qui se préoccupent par exemple d'afficher l’UI. Les HOC utilisent des conteneurs dans leur implémentation. Vous pouvez voir les HOC comme des définitions paramétrables de composants conteneurs. -## Convention: transmettez les props sans rapport au composant enfant {#convention-pass-unrelated-props-through-to-the-wrapped-component} +## Convention : transmettez les props annexes au composant enrobé {#convention-pass-unrelated-props-through-to-the-wrapped-component} Les HOC ajoutent des fonctionnalités à un composant. Ils ne devraient pas drastiquement modifier son contrat. On s'attend à ce que le composant renvoyé par un HOC aie une interface semblable au composant initial. -Les HOC devraient transmettre les props sans rapport avec leurs propres préoccupations. La méthode de rendu de la plupart des HOC ressemble à ceci : +Les HOC devraient transmettre les props sans rapport avec leur propre fonctionnement. La plupart des HOC ont une méthode de rendu qui ressemble à ça : ```js render() { - // Filtre les props supplémentaires propres à ce HOC qui ne devraient pas être trasmises + // Filtre les props supplémentaires propres à ce HOC qui ne devraient pas être transmises const { extraProp, ...passThroughProps } = this.props; - // Injecte les props dans le composant enfant. Il s'agit en général de valeurs de l'état global ou de méthodes d'instance + // Injecte les props dans le composant enrobé. Il s'agit en général de valeurs de l'état local + // ou de méthodes d'instance. const injectedProp = someStateOrInstanceMethod; - // Transmet les props au composant enfant + // Transmet les props au composant enrobé return ( Composant`. Les fonctions dont le type de données est le même à la sortie qu'à l'entrée sont beaucoup plus facile à composer. +Cette forme peut sembler déroutante ou superflue, pourtant elle a une propriété utile. Les HOC n'acceptant qu'un argument comme celui que renvoie la fonction `connect` ont une signature `Composant => Composant`. Les fonctions dont le type de données est le même à la sortie qu'à l'entrée sont beaucoup plus facile à composer. ```js // Plutôt que de faire ceci... @@ -281,7 +282,7 @@ const EnhancedComponent = withRouter(connect(commentSelector)(WrappedComponent)) // ... vous pouvez utiliser un utilitaire de composition de fonction // compose(f, g, h) est l'équivalent de (...args) => f(g(h(...args))) const enhance = compose( - // Ceux-ci sont tous deux des HOC n'acceptant qu'un argument + // Ces deux-là sont des HOC n'acceptant qu'un argument withRouter, connect(commentSelector) ) @@ -290,13 +291,13 @@ const EnhancedComponent = enhance(WrappedComponent) (C'est aussi cette propriété qui permet à `connect` et à d'autres HOC du même type d'être utilisés comme décorateurs, une proposition expérimentale JavaScript) -La fonction utilitaire `compose` est offerte par de nombreuses bibliothèqes tierces, y compris lodash (nommée [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose), et [Ramda](https://ramdajs.com/docs/#compose). +La fonction utilitaire `compose` est fournie par de nombreuses bibliothèques tierces, dont lodash (sous le nom [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose), et [Ramda](https://ramdajs.com/docs/#compose). -## Convention: enveloppez le nom d'affichage pour faciliter le débogage {#convention-wrap-the-display-name-for-easy-debugging} +## Convention : enrobez le `displayName` pour faciliter le débogage {#convention-wrap-the-display-name-for-easy-debugging} -Tout comme n'importe quel autre composant, les composants conteneurs créés par des HOC apparaîssent dans les [Outils de développement React](https://github.com/facebook/react-devtools). Pour faciliter votre débogage, donnez-leur un nom d'affichage qui signifie qu'ils ont été crées par des HOC. +Tout comme n'importe quel autre composant, les composants conteneurs créés par des HOC apparaissent dans les [Outils de développement React](https://github.com/facebook/react-devtools). Pour faciliter votre débogage, donnez-leur un nom affichable qui indique qu'ils sont le résultat d'un HOC. -Le technique ls plus commune est d'envelopper le nom d'affichage du composant enfant. Par exemple, si votre composant d'ordre supérieur s'appelle `withSubscription`, et que le nom d'affichage du composant enfant est `CommentList`, utilisez le nom d'affichage `WithSubscription(CommentList)` : +Le technique la plus répandue consiste à enrober le nom d'affichage du composant enrobé. Par exemple, si votre composant d'ordre supérieur s'appelle `withSubscription`, et que le nom d'affichage du composant enrobé est `CommentList`, utilisez le nom d'affichage `WithSubscription(CommentList)` : ```js function withSubscription(WrappedComponent) { @@ -311,37 +312,37 @@ function getDisplayName(WrappedComponent) { ``` -## Avertissements {#caveats} +## Limitations {#caveats} -L'utilisation de composants d'ordre supérieur comporte quelques risques qui ne seront pas tout de suite évidents si vous débutez avec React. +L'utilisation de composants d'ordre supérieur est sujette à quelques limitations qui ne sont pas tout de suite évidentes si vous débutez avec React. ### Pas de HOC à l'intérieur de la méthode de rendu {#dont-use-hocs-inside-the-render-method} -L'algorithme de différentiation de React (qu'on appelle réconcilation) utilise l'identité des composants pour déterminer s'il faut mettre à jour l'arborescence existante ou en monter une nouvelle. Si le composant renvoyé par `render` est identique (`===`) au composant du rendu précédent, React met à jour l'ancienne arborescence en la différenciant résursivement avec la nouvelle. S'ils ne sont pas identiques, l'ancienne arborescence est intégralement démontée. +L'algorithme de comparaison de React (qu'on appelle la réconciliation) utilise l'identité des composants pour déterminer s'il faut mettre à jour l'arborescence existante ou la jeter et en monter une nouvelle. Si le composant renvoyé par `render` est identique (`===`) au composant du rendu précédent, React met récursivement à jour l'arborescence en la comparant avec la nouvelle. S'ils ne sont pas identiques, l'ancienne arborescence est intégralement démontée. -En général, vous ne devriez pas avoir à y penser. Mais dans le cadre des HOC, cela importe puisque cela signifie que vous ne pouvez pas appliquer un HOC au sein de la méthode de rendu d'un composant : +En général, vous ne devriez pas avoir à y penser. Mais dans le cadre des HOC c'est important, puisque ça signifie que vous ne pouvez pas appliquer un HOC au sein de la méthode de rendu d'un composant : ```js render() { // Une nouvelle version de EnhancedComponent est créée à chaque rendu // EnhancedComponent1 !== EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); - // Cela cause le démontage et remontage de toute l'arborescence à chaque fois ! + // Ça entraîne un démontage/remontage complet à chaque fois ! return ; } ``` -Il ne s'agit pas uniquement d'un problème de performance—remonter un composant signifie que l'état local de ce composant ainsi que celui de tous ses enfants sera perdu. +Il ne s'agit pas uniquement d'un problème de performance : remonter un composant signifie que l'état local de ce composant ainsi que ceux de tous ses enfants seront perdus. -Appliquez plutôt les HOC à l'extérieur de la définition d'un composant, afin de créer le composant final une seule fois. Son identité sera alors constante lors des rendus. C'est normalement ce que vous voulez, non ? +Appliquez plutôt les HOC à l'extérieur de la définition d'un composant, afin de créer le composant enrobé une seule fois. Son identité sera alors constante d’un rendu à l'autre. C'est généralement ce que vous voulez, de toutes façons. -Dans les rares cas où vous devriez appliquer un HOC de façon dynamique, vous pouvez le faire au sein des méthodes de cycle de vie d'un composant ou dans son contructeur. +Dans les rares cas où vous avez besoin d’appliquer un HOC de façon dynamique, vous pouvez le faire au sein des méthodes de cycle de vie d'un composant ou dans son constructeur. ### Les méthodes statiques doivent être copiées {#static-methods-must-be-copied-over} Il est parfois utile de définir une méthode statique dans un composant React. Par exemple, les conteneurs Relay exposent une méthode statique `getFragment` pour simplifier la composition de fragments GraphQL. -Cependant, quand vous appliquez un HOC à un composant, le composant initial est enveloppé par un composant conteneur. Cela signifie que le nouveau composant ne comporte aucune des méthodes statiques du composant initial. +Cependant, quand vous appliquez un HOC à un composant, le composant initial est enrobé par un composant conteneur. Ça signifie que le nouveau composant ne comporte aucune des méthodes statiques du composant initial. ```js // Définit une méthode statique @@ -353,18 +354,18 @@ const EnhancedComponent = enhance(WrappedComponent); typeof EnhancedComponent.staticMethod === 'undefined' // true ``` -Pour résoudre cela, vous pouvez copier les méthodes dans le conteneur avant de le renvoyer : +Pour résoudre ça, vous pouvez copier les méthodes dans le conteneur avant de le renvoyer : ```js function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} - // Doit connaître exactement quelles méthodes recopier :( + // Doit savoir exactement quelles méthodes recopier :( Enhance.staticMethod = WrappedComponent.staticMethod; return Enhance; } ``` -Par contre, cela exige que vous sachiez exactement quelles méthodes doivent être copiées. Vous pouvez autrement utiliser [hoist-non-react-statics](https://github.com/mridgway/hoist-non-react-statics) qui copie automatiquement toutes les méthodes statiques : +Le problème, c’est que ça exige que vous sachiez exactement quelles méthodes doivent être recopiées. Vous devriez plutôt utiliser [hoist-non-react-statics](https://github.com/mridgway/hoist-non-react-statics) pour copier automatiquement toutes les méthodes statiques qui ne viennent pas de React : ```js import hoistNonReactStatic from 'hoist-non-react-statics'; @@ -391,6 +392,6 @@ import MyComponent, { someFunction } from './MyComponent.js'; ### Les refs ne sont pas transmises {#refs-arent-passed-through} -Bien que que la convention pour les composants d'ordre supérieur soit de transmettre toutes les props au composant enfant, elle ne s'applique pas aux refs. Une `ref` n'est en effet pas vraiment une prop—comme une `key`, React la traite de façon particulière. Si vous ajoutez une ref à un élément dont le composant résulte d'un HOC, la ref fait référence à une instance du composant conteneur le plus à l'extérieur, et non pas au composant enfant. +Bien que que la convention pour les composants d'ordre supérieur soit de transmettre toutes les props au composant enrobé, ça ne marche pas pour les refs. C'est parce que `ref` n'est pas vraiment une prop : comme `key`, React la traite de façon particulière. Si vous ajoutez une ref à un élément dont le composant résulte d'un HOC, la ref fait référence à une instance du composant conteneur extérieur, et non au composant enrobé. La solution à ce problème réside dans l'utilisation de l'API `React.forwardRef` (introduite dans React 16.3). [Apprenez-en davantage dans la section sur la transmission des refs](/docs/forwarding-refs.html). From fdaeaaf0711d61b5190882e500930e4a4bba427a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=A9tral?= Date: Thu, 14 Mar 2019 15:43:53 +0100 Subject: [PATCH 30/31] Translate text in code block's console.log() --- content/docs/higher-order-components.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 23e691524..26895c3fd 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -199,8 +199,8 @@ Plutôt que la mutation, les HOC devraient utiliser la composition, en enrobant function logProps(WrappedComponent) { return class extends React.Component { componentWillReceiveProps(nextProps) { - console.log('Current props: ', this.props); - console.log('Next props: ', nextProps); + console.log('Props actuelles : ', this.props); + console.log('Prochaines props : ', nextProps); } render() { // Enrobe le composant initial dans un conteneur, sans le modifier. C’est mieux ! From fd4f17dbc270625f58e9b7ff278f1de9021aec6a Mon Sep 17 00:00:00 2001 From: Christophe Porteneuve Date: Thu, 14 Mar 2019 16:18:17 +0100 Subject: [PATCH 31/31] Final tweaks --- content/docs/higher-order-components.md | 83 +++++++++++++------------ 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 26895c3fd..f62e723b4 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -1,10 +1,10 @@ --- id: higher-order-components -title: Composants d'ordre supérieur +title: Composants d’ordre supérieur permalink: docs/higher-order-components.html --- -Un composant d'ordre supérieur *(Higher-Order Component ou HOC, NdT)* est une technique avancée de React qui permet de réutiliser la logique de composants. Les HOC ne font pas partie de l'API de React à proprement parler, mais découlent de la nature compositionnelle de React. +Un composant d'ordre supérieur *(Higher-Order Component ou HOC, NdT)* est une technique avancée de React qui permet de réutiliser la logique de composants. Les HOC ne font pas partie de l'API de React à proprement parler, mais découlent de sa nature compositionnelle. Concrètement, **un composant d'ordre supérieur est une fonction qui accepte un composant et renvoie un nouveau composant.** @@ -26,7 +26,7 @@ Dans ce guide, nous verrons pourquoi les composants d'ordre supérieurs sont uti Les composants sont le principal moyen de réutiliser du code en React. Cependant, vous remarquerez que les composants classiques ne conviennent pas à tous les modèles. -Imaginez que vous ayez créé un composant `CommentList` qui écoute une source externe de données pour afficher une liste de commentaires : +Imaginez que vous ayez créé un composant `CommentList` qui s’abonne à une source externe de données pour afficher une liste de commentaires : ```js class CommentList extends React.Component { @@ -34,13 +34,13 @@ class CommentList extends React.Component { super(props); this.handleChange = this.handleChange.bind(this); this.state = { - // "DataSource" est une source de données quelconque + // `DataSource` est une source de données quelconque comments: DataSource.getComments() }; } componentDidMount() { - // On s'abonne aux modifications + // On s’abonne aux modifications DataSource.addChangeListener(this.handleChange); } @@ -50,7 +50,7 @@ class CommentList extends React.Component { } handleChange() { - // Met à jour l'état local quand la source de données est modifiée + // Met à jour l’état local quand la source de données est modifiée this.setState({ comments: DataSource.getComments() }); @@ -106,9 +106,9 @@ class BlogPost extends React.Component { - Dans l'écouteur, ils appellent `setState` quand la source de données est modifiée. - Au démontage *(quand le composant sort de la couche d'affichage, NdT)*, ils enlèvent l'écouteur d'événements. -Vous imaginez bien que dans une appli importante, ce motif d'abonnement à une `DataSource` et d'appel à `setState` sera récurrent. Il nous faut une abstraction qui nous permette de définir cette logique à un seul endroit et de la réutiliser pour de nombreux composants. C'est là que les composants d'ordre supérieur sont particulièrement utiles. +Vous imaginez bien que dans une appli importante, ce motif d'abonnement à une `DataSource` et d'appel à `setState` sera récurrent. Il nous faut une abstraction qui nous permette de définir cette logique en un seul endroit et de la réutiliser pour de nombreux composants. C'est là que les composants d'ordre supérieur sont particulièrement utiles. -Nous pouvons écrire une fonction qui crée des composants qui s'abonnent à une `DataSource`, comme `CommentList` et `BlogPost`. La fonction acceptera parmi ses arguments un composant enfant, qui recevra les données suivies en props. Appelons cette fonction `withSubscription` : +Nous pouvons écrire une fonction qui crée des composants qui s'abonnent à une `DataSource`, comme `CommentList` et `BlogPost`. La fonction acceptera parmi ses arguments un composant initial, qui recevra les données suivies en props. Appelons cette fonction `withSubscription` : ```js const CommentListWithSubscription = withSubscription( @@ -122,7 +122,7 @@ const BlogPostWithSubscription = withSubscription( ); ``` -Le premier paramètre est le composant enfant. Le second récupère les données qui nous intéressent, en fonction de la `DataSource` et des props existantes. +Le premier paramètre est le composant initial. Le second récupère les données qui nous intéressent, en fonction de la `DataSource` et des props existantes. Lorsque `CommentListWithSubscription` et `BlogPostWithSubscription` s'affichent, `CommentList` et `BlogPost` reçoivent une prop `data` qui contient les données les plus récentes issues de la `DataSource` : @@ -140,7 +140,7 @@ function withSubscription(WrappedComponent, selectData) { } componentDidMount() { - // ... qui s'occupe de l'abonnement... + // ... qui s’occupe de l'abonnement... DataSource.addChangeListener(this.handleChange); } @@ -155,8 +155,8 @@ function withSubscription(WrappedComponent, selectData) { } render() { - // ... et affiche composant enfant avec les données à jour ! - // Remarquez qu'on passe aussi toute autre prop reçue + // ... et affiche le composant enrobé avec les données à jour ! + // Remarquez qu’on passe aussi toute autre prop reçue. return ; } }; @@ -165,27 +165,27 @@ function withSubscription(WrappedComponent, selectData) { Remarquez qu'un HOC ne modifie pas le composant qu'on lui passe, et ne recourt pas non plus à l’héritage pour copier son comportement. Un HOC *compose* le composant initial en l'*enrobant* dans un composant conteneur. Il s'agit d'une fonction pure, sans effets de bord. -Et voilà ! Le composant enfant reçoit toutes les props du conteneur ainsi qu'une nouvelle prop, `data`, qu'il emploie pour produire son résultat. Le HOC ne se préoccupe pas de savoir comment ou pourquoi les données sont utilisées, et le composant enfant ne se préoccupe pas de savoir d'où les données viennent. +Et voilà ! Le composant enrobé reçoit toutes les props du conteneur ainsi qu'une nouvelle prop, `data`, qu'il emploie pour produire son résultat. Le HOC ne se préoccupe pas de savoir comment ou pourquoi les données sont utilisées, et le composant enrobé ne se préoccupe pas de savoir d'où viennent les données. Puisque `withSubscription` est juste une fonction, vous pouvez lui définir autant ou aussi peu de paramètres que vous le souhaitez. Par exemple, vous pourriez rendre configurable le nom de la prop `data`, afin d’isoler encore davantage le HOC et le composant enrobé. Ou alors, vous pourriez accepter un argument qui configure `shouldComponentUpdate`, ou un autre qui configure la source de données. Tout ça est possible parce que le HOC a un contrôle total sur la façon dont le composant est défini. Comme pour les composants, le rapport entre `withSubscription` et le composant enrobé se base entièrement sur les props. Ça facilite l'échange d'un HOC pour un autre, du moment qu'ils fournissent les mêmes props au composant enrobé. Ça peut s'avérer utile si vous changez de bibliothèque pour récupérer vos données, par exemple. -## Ne modifiez pas le composant initial. Composez-le. {#dont-mutate-the-original-component-use-composition} +## Ne modifiez pas le composant initial : composez-le. {#dont-mutate-the-original-component-use-composition} Résistez à la tentation de modifier le prototype d'un composant (ou de le modifier de quelque façon que ce soit) dans un HOC. ```js function logProps(InputComponent) { InputComponent.prototype.componentWillReceiveProps = function(nextProps) { - console.log('Current props: ', this.props); - console.log('Next props: ', nextProps); + console.log('Props actuelles : ', this.props); + console.log('Prochaines props : ', nextProps); }; - // Le fait que le composant initial soit renvoyé est un signe qu'il a été modifié. + // Le fait que le composant initial soit renvoyé est un signe qu’il a été modifié. return InputComponent; } -// EnhancedComponent fera un log à chaque fois qu'il reçoit des props +// EnhancedComponent fera un log à chaque fois qu’il reçoit des props. const EnhancedComponent = logProps(InputComponent); ``` @@ -199,34 +199,35 @@ Plutôt que la mutation, les HOC devraient utiliser la composition, en enrobant function logProps(WrappedComponent) { return class extends React.Component { componentWillReceiveProps(nextProps) { - console.log('Props actuelles : ', this.props); - console.log('Prochaines props : ', nextProps); + console.log('Props actuelles : ', this.props); + console.log('Prochaines props : ', nextProps); } render() { - // Enrobe le composant initial dans un conteneur, sans le modifier. C’est mieux ! + // Enrobe le composant initial dans un conteneur, sans le modifier. Mieux ! return ; } } } ``` -Ce HOC a la même fonctionnalité que la version modifiante, tout en évitant le risque de confits. Il fonctionne tout aussi bien avec les composants à base de classe et les fonctions composants. Et puisqu'il s'agit d'une fonction pure, il est composable avec d'autres HOC voire même avec lui-même. +Ce HOC a la même fonctionnalité que la version modifiante, tout en évitant le risque de conflits. Il fonctionne tout aussi bien avec les composants à base de classe et les fonctions composants. Et puisqu'il s'agit d'une fonction pure, il est composable avec d'autres HOC voire même avec lui-même. Vous avez peut-être remarqué des ressemblances entre les HOC et le motif des **composants conteneurs**. Les composants conteneurs participent à des stratégies de séparation de responsabilités entre les préoccupations de haut et de bas niveau. Les conteneurs se préoccupent par exemple des abonnements et de l'état, et passent des props à d'autres composants qui se préoccupent par exemple d'afficher l’UI. Les HOC utilisent des conteneurs dans leur implémentation. Vous pouvez voir les HOC comme des définitions paramétrables de composants conteneurs. ## Convention : transmettez les props annexes au composant enrobé {#convention-pass-unrelated-props-through-to-the-wrapped-component} -Les HOC ajoutent des fonctionnalités à un composant. Ils ne devraient pas drastiquement modifier son contrat. On s'attend à ce que le composant renvoyé par un HOC aie une interface semblable au composant initial. +Les HOC ajoutent des fonctionnalités à un composant. Ils ne devraient pas drastiquement modifier son contrat. On s'attend à ce que le composant renvoyé par un HOC ait une interface semblable au composant initial. Les HOC devraient transmettre les props sans rapport avec leur propre fonctionnement. La plupart des HOC ont une méthode de rendu qui ressemble à ça : ```js render() { - // Filtre les props supplémentaires propres à ce HOC qui ne devraient pas être transmises + // Filtre les props supplémentaires propres à ce HOC + // qui ne devraient pas être transmises const { extraProp, ...passThroughProps } = this.props; - // Injecte les props dans le composant enrobé. Il s'agit en général de valeurs de l'état local - // ou de méthodes d'instance. + // Injecte les props dans le composant enrobé. Il s’agit en général + // de valeurs de l’état local ou de méthodes d’instance. const injectedProp = someStateOrInstanceMethod; // Transmet les props au composant enrobé @@ -239,11 +240,11 @@ render() { } ``` -Cette convention aide à garantir que les HOC sont aussi flexibles et réutilisables que possible. +Cette convention améliore la flexibilité et la réutilisabilité de nos HOC. ## Convention : maximisez la composabilité {#convention-maximizing-composability} -Tous les HOC ne sont pas pareils. Ils n'acceptent parfois qu'un seul argument, le composant enrobé : +Tous les HOC n’ont pas la même interface. Ils n'acceptent parfois qu'un seul argument, le composant enrobé : ```js const NavbarWithRouter = withRouter(Navbar); @@ -271,25 +272,25 @@ const enhance = connect(commentListSelector, commentListActions); const ConnectedComment = enhance(CommentList); ``` -Autrement dit, `connect` est une fonction d'ordre supérieur qui renvoie un composant d'ordre supérieur ! +Autrement dit, `connect` est une fonction d'ordre supérieur… qui renvoie un composant d'ordre supérieur ! -Cette forme peut sembler déroutante ou superflue, pourtant elle a une propriété utile. Les HOC n'acceptant qu'un argument comme celui que renvoie la fonction `connect` ont une signature `Composant => Composant`. Les fonctions dont le type de données est le même à la sortie qu'à l'entrée sont beaucoup plus facile à composer. +Cette forme peut sembler déroutante ou superflue, pourtant elle a une propriété utile. Les HOC n'acceptant qu'un argument comme celui que renvoie la fonction `connect` ont une signature `Composant => Composant`. Les fonctions dont le type de données est le même en sortie qu'en entrée sont beaucoup plus faciles à composer. ```js // Plutôt que de faire ceci... const EnhancedComponent = withRouter(connect(commentSelector)(WrappedComponent)) -// ... vous pouvez utiliser un utilitaire de composition de fonction -// compose(f, g, h) est l'équivalent de (...args) => f(g(h(...args))) +// ... vous pouvez utiliser un utilitaire de composition de fonction. +// compose(f, g, h) est l’équivalent de (...args) => f(g(h(...args))) const enhance = compose( - // Ces deux-là sont des HOC n'acceptant qu'un argument + // Ces deux-là sont des HOC n’acceptant qu’un argument. withRouter, connect(commentSelector) ) const EnhancedComponent = enhance(WrappedComponent) ``` -(C'est aussi cette propriété qui permet à `connect` et à d'autres HOC du même type d'être utilisés comme décorateurs, une proposition expérimentale JavaScript) +(C'est aussi cette propriété qui permet à `connect` et à d'autres HOC du même type d'être utilisés comme décorateurs, une proposition expérimentale JavaScript.) La fonction utilitaire `compose` est fournie par de nombreuses bibliothèques tierces, dont lodash (sous le nom [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose), et [Ramda](https://ramdajs.com/docs/#compose). @@ -332,7 +333,7 @@ render() { } ``` -Il ne s'agit pas uniquement d'un problème de performance : remonter un composant signifie que l'état local de ce composant ainsi que ceux de tous ses enfants seront perdus. +Il ne s'agit pas uniquement d'un problème de performances : remonter un composant signifie que l'état local de ce composant ainsi que ceux de tous ses enfants seront perdus. Appliquez plutôt les HOC à l'extérieur de la définition d'un composant, afin de créer le composant enrobé une seule fois. Son identité sera alors constante d’un rendu à l'autre. C'est généralement ce que vous voulez, de toutes façons. @@ -350,7 +351,7 @@ WrappedComponent.staticMethod = function() {/*...*/} // Applique un HOC const EnhancedComponent = enhance(WrappedComponent); -// Le composant amélioré n'a pas de méthode statique +// Le composant amélioré n’a pas de méthode statique typeof EnhancedComponent.staticMethod === 'undefined' // true ``` @@ -368,15 +369,15 @@ function enhance(WrappedComponent) { Le problème, c’est que ça exige que vous sachiez exactement quelles méthodes doivent être recopiées. Vous devriez plutôt utiliser [hoist-non-react-statics](https://github.com/mridgway/hoist-non-react-statics) pour copier automatiquement toutes les méthodes statiques qui ne viennent pas de React : ```js -import hoistNonReactStatic from 'hoist-non-react-statics'; +import hoistNonReactStatics from 'hoist-non-react-statics'; function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} - hoistNonReactStatic(Enhance, WrappedComponent); + hoistNonReactStatics(Enhance, WrappedComponent); return Enhance; } ``` -Une autre solution consiste à exporter les méthodes statiques séparément du composant lui-même. +Une autre solution consiste à exporter les méthodes statiques de façon séparée du composant lui-même. ```js // Plutôt que... @@ -386,7 +387,7 @@ export default MyComponent; // ... exportez les méthodes séparément... export { someFunction }; -// ... et dans le module qui les utilise, importez les deux +// ... et dans le module qui les utilise, importez les deux. import MyComponent, { someFunction } from './MyComponent.js'; ``` @@ -394,4 +395,4 @@ import MyComponent, { someFunction } from './MyComponent.js'; Bien que que la convention pour les composants d'ordre supérieur soit de transmettre toutes les props au composant enrobé, ça ne marche pas pour les refs. C'est parce que `ref` n'est pas vraiment une prop : comme `key`, React la traite de façon particulière. Si vous ajoutez une ref à un élément dont le composant résulte d'un HOC, la ref fait référence à une instance du composant conteneur extérieur, et non au composant enrobé. -La solution à ce problème réside dans l'utilisation de l'API `React.forwardRef` (introduite dans React 16.3). [Apprenez-en davantage dans la section sur la transmission des refs](/docs/forwarding-refs.html). +La solution à ce problème réside dans l'utilisation de l'API `React.forwardRef` (introduite dans React 16.3). [Vous pouvez en apprendre davantage dans la section sur la transmission des refs](/docs/forwarding-refs.html).