Skip to content

Commit

Permalink
Fix typos (#794)
Browse files Browse the repository at this point in the history
  • Loading branch information
Edouard Alvard authored and MoOx committed Jul 17, 2018
1 parent e4a290c commit 3143efe
Showing 1 changed file with 84 additions and 26 deletions.
110 changes: 84 additions & 26 deletions content/fr/articles/js/react/react-new-context-api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,60 @@ tags:
authors:
- neovea
---
Depuis fin mars 2018, la version 16.3 de React est sortie, et elle vient avec son lot de nouveautés, dont celle dont j'aimerais vous parler dans cet article : l'API Context. Alors OK, cette API existait déjà par le passé mais il était déconseillé de l'utiliser car sujette à évolution (c'est la doc de React qui le dit). Et évolution il y a eu. La nouvelle API Context est devenue beaucoup plus facile à utiliser, sa syntaxe s'est assouplie et s'est simplifiée. Ce qui fait d'elle un outil de premier ordre désormais.

Depuis fin mars 2018, la version 16.3 de React est sortie et a apporté son lot
de nouveautés, dont l'API Context. Alors ok, cette API existait déjà par le
passé mais il était déconseillé de l'utiliser car sujette à évolution (c'est la
doc de React qui le disait). Et évolution il y a eu. La nouvelle API Context est
devenue beaucoup plus facile à utiliser ; sa syntaxe s'est assouplie et
simplifiée. Ce qui fait désormais d'elle un outil de premier ordre.

## À quoi ça sert exactement ?
Ça permet tout simplement de rendre disponibles des propriétés au sein des ses composants React sans avoir à les passer directement à ces derniers. Autant dire que lorsqu'on a une application un peu complexe (entendre beaucoup de composants et d'héritages de propriétés), il devient très vite compliqué de maintenir tout ce petit monde ensemble. De plus cela pose un souci de performance non négligeable à la longue puisque les données sont traitées par des composants qui n'ont rien à faire avec, sans compter les `render` potentiellement inutiles.
Du coup très souvent on a recours à des solutions qui peuvent se montrer potentiellement *overkill* (aka Redux, Mobx et consorts) afin de ségréguer tout ou partie de nos données pour des composants spécifiques, et les rendre disponibles "facilement" à l'ensemble de l'app.

Avec la nouvelle API Context, on peut facilement se créer un ou plusieurs stores pour nos données, ce qui permet entre autres de mieux les structurer, mais aussi de passer à ses composants la juste quantité de données, sans avoir à faire face au calamiteux *[prop drilling](https://blog.kentcdodds.com/prop-drilling-bb62e02cb691)*. Mais attention tout de même à ne pas en faire un marteau doré.
Ça permet tout simplement de rendre disponibles des propriétés au sein des ses
composants React sans avoir à les passer directement à ces derniers. Autant dire
que lorsqu'on a une application un peu complexe (entendre beaucoup de composants
et d'héritages de propriétés), il devient très vite compliqué de maintenir tout
ce petit monde ensemble. De plus, cela pose un souci de performance non
négligeable à la longue puisque les données sont traitées par des composants qui
n'ont rien à faire avec, sans compter les `Render`s potentiellement inutiles. Du
coup, très souvent, on a recours à des solutions qui peuvent se montrer
potentiellement _overkill_ (aka Redux, Mobx et consorts) afin de ségréguer tout
ou partie de nos données pour des composants spécifiques, et les rendre
disponibles "facilement" à l'ensemble de l'app.

Avec la nouvelle API Context, on peut facilement créer un ou plusieurs `store`s
pour nos données. Cela permet de mieux structurer nos données, mais aussi d'en
passer la juste quantité nos composants, sans avoir à faire face au calamiteux
_[prop drilling](https://blog.kentcdodds.com/prop-drilling-bb62e02cb691)_. Mais
attention tout de même à ne pas en faire un marteau doré.

## À quoi ça ressemble dans la pratique ?
Assez de blabla, passons à un exemple concret avec des vrais morceaux de `Context` dedans !

Imaginons que je souhaite créer un contexte qui contiendrait les informations de l'utilisateur connecté pour les rendre facilement accessibles à plusieurs endroits de mon app, nous créons un contexte et l'implémentons de la manière suivante :
Assez de blabla, passons à un exemple concret avec des vrais morceaux de
`Context` dedans !

Imaginons que nous souhaitions créer un contexte qui contient les informations
de l'utilisateur connecté pour les rendre facilement accessibles à plusieurs
endroits de notre app. Nous créons un contexte et l'implémentons de la manière
suivante :

### Création du contexte

```jsx
// store/UserProvider.js
import React, { createContext, Component } from "react"; // on importe createContext qui servira à la création d'un ou plusieurs contextes

/**
* `createContext` contient 2 propriétés :
* `Provider` et `Consumer`. Nous les rendons accessibles
* via la constante `UserContext`, et on initialise une
* propriété par défaut : "name" qui sera une chaîne vide.
* via la constante `UserContext` et on initialise une
* propriété par défaut "name" qui sera une chaîne vide.
* On exporte ce contexte afin qu'il soit exploitable par
* d'autres composants par la suite via le `Consumer`
*/
export const UserContext = createContext({
name: ""
name: "",
});

/**
Expand All @@ -43,7 +71,7 @@ export const UserContext = createContext({
*/
class UserProvider extends Component {
state = {
name: "Putain de Code" // une valeur de départ
name: "Putain de Code", // une valeur de départ
};

render() {
Expand All @@ -60,9 +88,10 @@ class UserProvider extends Component {
}

export default UserProvider;

```

### Initialisation du contexte

```jsx
// app.js
import React from "react";
Expand All @@ -74,7 +103,7 @@ import UserProvider from "./store/UserProvider";

const styles = {
fontFamily: "sans-serif",
textAlign: "center"
textAlign: "center",
};

const App = () => (
Expand All @@ -93,10 +122,10 @@ render(
<UserProvider>
<App />
</UserProvider>,
document.getElementById("root")
document.getElementById("root"),
);

```

### Création du composant `Hello` qui consommera les data de notre contexte

```jsx
Expand All @@ -117,23 +146,40 @@ export default () => (
{value => <h1>Hello {value.name}!</h1>}
</UserContext.Consumer>
);

```

### Le rendu sera :

```html
<h1>Hello Putain de Code!</h1>
```
En gros, ce qu'il faut retenir ici, c'est que pour utiliser l'API, on a deux propriétés : Le `Provider`, qui se charge de diffuser nos propriétés d'une part, et un ou plusieurs `Consumer` qui permettent d'accéder aux données fournies par le `Provider` d'autre part.

Avec cet exemple minimaliste, on constate qu'il n'est plus nécessaire de passer les `props` à nos composants enfants. Ceci rend du coup le code plus light et plus facile à lire et à comprendre. Et ça c'est déjà énorme en soi. Petite note en passant : vos composants qui se nourrissent de votre contexte seront re-rendus à chaque fois que ce dernier sera mis à jour. Donc faites gaffe quand même à ne pas en abuser. Mais avec une bonne gestion on peut aller assez loin :)
En gros, ce qu'il faut retenir ici, c'est que pour utiliser l'API, on a deux
propriétés : le `Provider`, qui se charge de diffuser nos propriétés d'une part,
et un ou plusieurs `Consumer`s qui permettent d'accéder aux données fournies par
le `Provider` d'autre part.

Avec cet exemple minimaliste, on constate qu'il n'est plus nécessaire de passer
les `props` à nos composants enfants. Ceci rend le code plus light et plus
facile à lire et à comprendre. Et ça c'est déjà énorme en soi. Petite note en
passant : vos composants qui se nourrissent de votre contexte seront re-rendus à
chaque fois que ce dernier sera mis à jour. Donc faites gaffe quand même à ne
pas en abuser. Mais avec une bonne gestion on peut aller assez loin :)

Bon c'est bien tout ça mais si on veut permettre à nos composants de modifier les valeurs de notre contexte ??
Bon c'est bien tout ça, mais si on veut permettre à nos composants de modifier
les valeurs de notre contexte ?

## Passer des méthodes à nos composants via `Context`
La partie la plus fun commence : on va enrichir notre contexte avec des méthodes qui seront accessibles aux enfants, et créer un store "à la Redux" en quelques lignes de code seulement ! 😈

La partie la plus fun commence : on va enrichir notre contexte avec des méthodes
qui seront accessibles aux enfants, et créer un `store` "à la Redux" en quelques
lignes de code seulement ! 😈

### Implémenter une méthode
On va déclarer notre méthode à deux endroits : Dans le `context`, et dans le `state` de notre `UserProvider` :

On va déclarer notre méthode à deux endroits : Dans le `context`, et dans le
`state` de notre `UserProvider` :

```jsx
// store/UserProvider.js
...
Expand Down Expand Up @@ -171,17 +217,19 @@ class UserProvider extends Component {
}

export default UserProvider;

```

Comme implémenter le `Consumer` dans chaque composant c'est rébarbatif, ce qu'on va faire c'est qu'on va créer un Higher Order Component qui se chargera d'implémenter ce dernier à notre place :
Comme implémenter le `Consumer` dans chaque composant est rébarbatif, on va
créer un Higher Order Component qui se chargera d'implémenter ce dernier à notre
place :

```jsx
// store/UserProvider.js

...

/**
* À la suite de notre classe `UserProvider`, on créé notre HOC
* A la suite de notre classe `UserProvider`, on créé notre HOC
* qui se chargera d'injecter les propriétés de notre contexte
* à n'importe quel composant qui l'appellera
*/
Expand All @@ -191,7 +239,9 @@ export const withUser = Component => props => (
</UserContext.Consumer>
)
```

Il ne reste plus qu'à modifier notre composant `Hello` comme suit :

```jsx
// Hello.js
import React, { Fragment } from "react";
Expand All @@ -210,14 +260,22 @@ export default withUser(({ name, setName }) => (
<input type="text" value={name} onChange={e => setName(e.target.value)} />
</Fragment>
));

```

Et tadam ✨✨ ! On a créé un micro store pour notre application !

## En conclusion
Avec l'API Context, les possibilités sont nombreuses : On peut créer des "micro stores" pour certaines parties de notre application, voire les faire hériter d'un store plus global. On peut aussi imaginer combiner les stores et les faire "hériter" les uns des autres.

On résout au passage pas mal de problèmes liés à l'imbrication et à la hiérarchisation des composants. Aussi on peut très facilement faire face à une application qui grossit sans avoir à sortir l'artillerie parfois lourde de Redux.
Avec l'API Context, les possibilités sont nombreuses, on peut :

- créer des "micro stores" pour certaines parties de notre application, voire
les faire hériter d'un store plus global.
- imaginer combiner les `store`s et les faire "hériter" les uns des autres.

On résout au passage pas mal de problèmes liés à l'imbrication et à la
hiérarchisation des composants. Ainsi, on peut très facilement faire face à une
application qui grossit sans avoir à sortir l'artillerie parfois lourde de
Redux.

Maintenant vous avez le pouvoir ! Mais usez-en avec sagesse :)

Expand Down

0 comments on commit 3143efe

Please sign in to comment.