Couverture de l'article React.js #3 : Gérer vos données dans des stores natifs
Retour aux articles

L'agence

WanadevStudio

React.js #3 : Gérer vos données dans des stores natifs

Javascript

Il y a 7 ans

Photo de Louis GOURAIN auteur de l'article

Louis GOURAIN

Cet article est le dernier article d'une série de trois articles dans laquelle nous voyons comment bien débuter son projet React.

Retrouvez tous les articles ici :

Au cours de ce dernier article nous allons aborder le sujet de la gestion des stores dans React.js.

@ Un store permet de stocker des données de manière centralisée et partagées entre tous les composants de notre application.

Auparavant, les dépendances tierces comme Flux, Redux ou Mobx permettaient de gérer les données et coordonner les composants de nos applications complexes. Désormais, Facebook a intégré les Context et les Hooks qui permettent d'avoir un système de store natif. Si vous n’êtes pas à l’aise avec ce concept de store, nous allons l'aborder plus concrètement dans la suite de l'article.

Dans notre architecture, les stores de nos applications sont des services. Nous y avons défini un premier store themeStore.js qui nous servira d’exemple tout au long de cet article. Pour gérer le store nous utiliserons les fonctionnalités natives à React.js (depuis la version 16.8) : Context et Hooks. Ainsi nous ne parlerons pas de Redux ou encore de Mobx qui sont d’autres solutions de gestion du store pour React.js.

Rapide point sur l’avis de React.js sur comment gérer son store

A la question “Devenons nous utiliser une librairie de gestion d’état comme Redux ou Mobx ?”, la documentation nous redirige vers la réponse à “Faut-il utiliser Redux” sur le site de Redux. La réponse est “non” dans un premier temps et "oui" si le besoin d’une source de vérité unique (ie. un état global à notre application) se faire ressenti. Mais cela ajoute de la complexité à notre application.

Récemment, nous n’avons plus vraiment besoin de Redux grâce à l’ajout de nouvelles fonctionnalités dans React que nous verrons plus tard. Faisons d’abord un rappel sur le state et les props en React.

Rappel de concepts importants dans React.js : composant, props et state

Un composant peut s’écrire de deux façons différentes :

  • Soit sous forme d’une fonction :
function Welcome(props) {
   return <h1>Hello, {props.name}</h1>;
}
  • Soit sous forme d’une classe :
class Welcome extends React.Component {
   render() {
       return <h1>Hello, {this.props.name}</h1>;
   }
}

Les deux écritures sont équivalentes.

@ Dans le développement de React.js, il semblerait que l’écriture sous forme de fonction soit de plus en plus privilégiée sans pour autant abandonner celle sous forme de classe. En effet, l’équipe React rassure en affirmant que les composants classe seront toujours maintenus dans un futur proche.

^ Il est donc fortement recommandé de désormais écrire tous vos composants sous forme de fonction si vous êtes à minima sous la version 16.8 de React.js

Pour ce qui est des props, on peut voir ça comme les paramètres d’entrée à notre composant. Ainsi quand on écrira notre composant Welcome, de l’exemple précédent, on devra lui passer un attribut name.

La principale différence qui existait entre l’écriture de composant sous forme de fonction et de classe était la gestion de l’état (state) du composant et du cycle de vie d’un composant. Mais avec l’apparition des Hooks, l’écriture de composant sous forme de fonction apporte des fonctionnalités équivalentes (ou presque) au composant sous forme de classe. En tout cas, l’ambition de React.js est de couvrir toutes les fonctionnalités des classes pour les composants fonction. Nous vous présenterons plus en détails les Hooks pour la gestion du store mais je vous invite à vous renseigner pour le hook qui permet de bénéficier d'un état local dans une fonction composant et le hook qui permet d'exécuter des effets de bord dans une fonction composant si ça vous intéresse. 🤩

NB : peu importe l’écriture que vous choisirez, sachez qu’il existe une équivalence.

Pourquoi un gestionnaire de store ?

Prenons l’exemple de Redux qui, malgré qu’il ne soit plus nécessaire, permet d’apprendre de bons principes d’architecture du code.

store_comparison_without_with_redux

A gauche sans Redux (ou tout autre gestionnaire de store), lorsqu’un composant est mis à jour, un état (state) global à l’application doit être stocké dans le composant racine donc une mise à jour doit remonter jusqu’à la racine puis redescendre dans tous les composants qui ont besoin de cette information mise à jour. Ce qui est assez laborieux et coûteux car les composants intermédiaires par lesquels passent l'état n'en ont pas nécessairement besoin.

Avec Redux, on a un store qui est séparé du reste de l'application et qui peut être mis à jour depuis n’importe quel composant et qui sera mis à jour pour tous les composants qui sont abonnés au store.

Le store permet de simplifier les changements de données au sein de l’application en centralisant tout à un unique endroit.

Présentation de Context

Dans une application React, les données sont normalement passées de haut en bas (du parent aux enfants) mais grâce aux Context, il est possible de fonctionner différemment. Les Context permettent de partager des données entre les composants sans passer par les props explicitement.

store_with_redux

Dans l’image ci-dessus, les Context correspondent à la logique symbolisée par les flèches bleues. D'une part avec le Provider qui permet d'injecter le store dans l'application et d'autre part avec le Consumer qui permet de lire les données dans le store. Cela permet de “s’abonner” au store et donc de savoir quand une donnée est modifiée dans celui-ci. Une autre façon de consommer le store est via les Hooks comme nous allons le voir au prochain point.

Présentation de Hooks

Comme nous l’avons dit plus haut, les Hooks arrivent dans une logique où l’équipe de développement de React.js souhaite que les composants fonction aient toutes les fonctionnalités des composants classe. Dans cette optique, nous privilégierons les composants écrits sous forme de fonction car pour utiliser les Hooks nous devons être dans un composant fonction.

store_with_redux

Les flèches vertes de notre image ci-dessus correspondent à l'écriture dans le store. Tout comme pour la partie lecture du store, elle peut s'effectuer de deux façons. Soit avec les Hooks et plus particulièrement le Hook useContext ou avec le Context.Consumer qui retournent tous les deux une méthode dispatch qui permet de modifier l'état de notre store.

Un cas concret

Comme spécifié dans l’introduction, nous allons expliquer le fonctionnement de notre store avec le fichier themeStore.js. Voyons à quoi ressemble notre store, comment on peut lire les données qui s’y trouvent et enfin comment on peut modifier notre store.

1. Définition du store

Pour définir notre store nous allons donc utiliser les deux concepts vus précédemment, à savoir, les Context et les Hooks. Notre store se découpe en 3 parties.

La première partie est l’état initial de notre store, c’est un simple objet javascript :

const initialState = {
    theme: 'green',
};

Dans notre cas on souhaite partager à toute notre application le thème de notre application qui est une couleur, ici, le vert, par défaut.

La seconde partie est un reducer, plus simplement, une méthode qui va modifier l’état de notre application selon une action. Par exemple, nous allons définir une action changeTheme qui permettra de modifier la couleur du thème de notre application. Voyons à quoi ressemble cette méthode concrètement :

const reducer = (state, action) => {
   switch (action.type) {
       case 'changeTheme':
       return {
           ...state,
           theme: action.newTheme
       };
       default:
       return state;
   }
};

La troisième et dernière partie de notre fichier est la création d’un Context autour de notre store. On a besoin d’un Consumer qui permet aux composants de lire le store et de connaître son état en temps réel mais également de modifier son état. On a également besoin d’un Provider qui permet de “brancher” notre store à l’application.

const ThemeContext = createContext();

export const ThemeConsumer = ThemeContext.Consumer;
export const ThemeConsumerHook = () => useContext(ThemeContext);

export const ThemeProvider = ({children}) => (
   <ThemeContext.Provider value={useReducer(reducer, initialState)}>
       {children}
   </ThemeContext.Provider>
);

On commence par créer un Context que nous nommons ThemeContext. Nous exportons le Consumer de ce Context ainsi qu’un ThemeConsumerHook qui est le Hook React useContext. Ce sont deux façons de consommer et modifier l’état de notre store : soit par l’objet Consumer (pour les composants classe ou fonction), soit par le Hook (pour les composants fonction).

Enfin, nous exportons le Provider qui prend en paramètre un composant et qui le retourne entouré du Context Provider. Ceci permet au composant passé en paramètre de pouvoir accéder à ce store grâce au Hook useReducer qui prend en paramètre un reducer et l’état initial de notre store.

Au final, voici notre fichier themeStore.js :

import React, {createContext, useContext, useReducer} from 'react';

const initialState = {
    theme: 'green',
};

const reducer = (state, action) => {
   switch (action.type) {
       case 'changeTheme':
       return {
           ...state,
           theme: action.newTheme
       };
       default:
       return state;
   }
};

const ThemeContext = createContext();

export const ThemeConsumer = ThemeContext.Consumer;
export const ThemeConsumerHook = () => useContext(ThemeContext);

export const ThemeProvider = ({children}) => (
   <ThemeContext.Provider value={useReducer(reducer, initialState)}>
       {children}
   </ThemeContext.Provider>
);

2. Lecture du store dans les composants

Cette étape est elle-même composée de 2 sous-étapes :

  • utilisation du Provider de notre Contextpour “brancher” le store à notre application
  • utilisation du Consumer ou de la Consumer Hook pour lire le store

Premièrement, pour “brancher” notre store à notre application, il suffit d’entourer la balise de notre composant avec le Provider de notre store. Voici comment nous l’avons fait dans notre fichier App.js :

 <ThemeProvider>
     <Router>
       <Switch>
         {
           getRoutes().map((route, index) => {
             return <MyRoute exact {...route} key={index} />
           })
         }
         <Route component={NotFound} />
       </Switch>
     </Router>
   </ThemeProvider>

Pour revoir les explications sur le routing je vous invite à vous référer à l’article 2 de cette série. 😉

Notre composant ThemeProvider encapsule toute notre application. Nous l’importons depuis notre store tout simplement comme ceci :

import { ThemeProvider } from 'stores/themeStore';

(Pour tout savoir sur comment mettre en place les imports absolus, rendez-vous dans l’article 1 de cette série.)

Deuxièmement, pour consommer les données de notre store dans un composant englobé par le ThemeProvider, nous pouvons utiliser le ThemeConsumer pour les composants classe (ou fonction) ou bien le ThemeConsumerHook pour les composants fonction.

Voyons comment cela se présente avec un exemple :

const [{theme}, dispatch] : any = ThemeConsumerHook();

On appelle tout simplement le Hook ThemeConsumerHook qui provient de notre store. Celle-ci nous retourne deux paramètres avec en premier lieu l’état et en second lieu une méthode dispatch qui nous permet de mettre à jour le store. En utilisant l’affectation par décomposition d’un tableau et d’un objet on obtient directement la veleur de theme et la méthode dispatch...

Nous ne couvrirons pas la partie qui utilise ThemeConsumer car dans notre application nous utiliserons majoritairement le ThemeConsumerHook mais pour en savoir plus à ce sujet, vous pouvez vous rapprocher de la documentation de React.js à propos des Context.Consumer.

3. Ecriture dans le store depuis les composants

Concentrons nous également sur le cas avec le ThemeConsumerHook car c'est le plus courant dans notre cas mais il est tout à fait possible de faire la même chose avec le ThemeConsumer. Car ce sont deux façons de récupérer la méthode dispatch évoquée précédemment. Celle-ci permet de mettre à jour le store depuis un composant. Voyons comment nous pouvons l’utiliser avec cet exemple :

dispatch({
    type: 'changeTheme',
    newTheme: 'blue'
});

Nous passons un objet en paramètre de la méthode dispatch avec deux clés : type et newTheme. Il s’agit en fait d’un objet action. La première clé correspond au type de l’action. La deuxième clé newTheme est la nouvelle couleur du thème de notre application. Rappelez-vous, c’est au niveau du reducer que nous gérons les actions. C’est donc ici que nous définissons les actions possibles.

Pour conclure, voici un exemple de composant complet qui affiche un bouton au couleur du thème par défaut (vert) et qui après un click change de couleur (bleu), tout ça via le store :

import React from 'react';
import { ThemeConsumerHook } from 'stores/themeStore';

const Admin = () => {
   const [{theme}, dispatch] = ThemeConsumerHook();

   function handleClick() {
       dispatch({
           type: 'changeTheme',
           newTheme: 'blue'
       });
   }

   return (
       <>
           <h1>ADMIN</h1>
           <button
               style={{color: `${theme}`}}
               onClick={handleClick}
           >
               Make me blue!
           </button>
       </>
   );
}

export default Admin;

Merci d'avoir lu ce dernier article et suivi toute la série dédiée à l'initialisation d'un nouveau projet React.js scalable et organisé ! 😃

  • Couverture de l'article #2 - Module Federation et Vue à l'ère de l'IA : retour de la MadVue 2026
    #2 - Module Federation et Vue à l'ère de l'IA : retour de la MadVue 2026

    Il y a 3 mois

    Voici la seconde partie de mon retour sur la MadVue 2026, la conférence Vue.js qui s'est tenue à Madrid le 22 mai 2026. Si vous avez manqué le début, la première partie est juste ici :

    Après les fondations de l'application Vue moderne, on change d'échelle et d'époque. Dans cet article, on va voir comment partager des composants entre plusieurs applications Vue avec Module Federation, puis trois talks consacrés à Vue et l'intelligence artificielle : faire générer une interface en direct par un LLM, préparer son projet Vue pour les agents, et enfin apprendre le frontend à l'ère de l'IA.

    C'est parti !

    Photo de Louis GOURAIN auteur de l'article

    Louis GOURAIN

    Lire la suite
  • Couverture de l'article #1 - Temps réel, URLs typées, formulaires et toolchain : retour de la MadVue 2026
    #1 - Temps réel, URLs typées, formulaires et toolchain : retour de la MadVue 2026

    Il y a 3 mois

    Le 22 mai 2026, je me suis rendu à Madrid pour la MadVue 2026, la conférence espagnole dédiée à l'écosystème Vue.js. Une journée dense, neuf talks, et une tendance de fond très claire : entre une grosse moitié orientée IA et expérience développeur et une autre consacrée aux fondations qui rendent nos applications soutenables.

    Dans cette série de deux articles, je reviens sur l'ensemble des talks. En les lisant, vous aurez l'impression d'y avoir assisté.

    Cet article est le premier des deux, vous pourrez retrouver chaque partie de cette série ici :

    Dans ce premier article, on pose les fondations d'une application Vue moderne : on verra comment faire du temps réel proprement, comment en finir avec le parsing manuel des paramètres d'URL, un tout nouveau modèle pour construire ses composants de formulaire, l'avènement d'une toolchain JavaScript unifiée (Oxc, Rolldown), et ce qui nous attend avec Nuxt 5.

    Beaucoup de sujets à traiter, alors c'est parti !

    Photo de Louis GOURAIN auteur de l'article

    Louis GOURAIN

    Lire la suite
  • Couverture de l'article #4 - Construire un DOM Virtuel, les différentes méthodes de rendu et bien écrire ses tests : retour de la Vue.js Amsterdam 2023
    #4 - Construire un DOM Virtuel, les différentes méthodes de rendu et bien écrire ses tests : retour de la Vue.js Amsterdam 2023

    Il y a 3 ans

    Pour la première fois, Wanadev s’est rendu à la plus grosse conférence annuelle autour de Vue.js : la Vue.js Amsterdam 2023. J’ai eu l’honneur d’assister à la 5ème édition, couronnée par le retour d’Evan You, le créateur de Vue.js et Vite, en personne.

    Dans cette série de quatre articles, je vais vous faire revivre ces deux jours de conférences. En les lisant, vous aurez l’impression d’y avoir assisté !

    Cet article est le troisième des quatre, vous pourrez retrouver chaque partie de cette série ici :

    Dans cet article nous allons voir comment construire un Virtual DOM, on parlera des différentes façons de faire du rendu dans le web, de comment écrire des bons tests et plein d’autres choses.

    Beaucoup de sujets à traiter, alors, c’est parti !

    Photo de Louis GOURAIN auteur de l'article

    Louis GOURAIN

    Lire la suite
  • Couverture de l'article #3 - Vue.js en 2023, l'avenir de Vue Router, les patterns avec Pinia  : retour de la Vue.js Amsterdam 2023
    #3 - Vue.js en 2023, l'avenir de Vue Router, les patterns avec Pinia : retour de la Vue.js Amsterdam 2023

    Il y a 3 ans

    Pour la première fois, Wanadev s’est rendu à la plus grosse conférence annuelle autour de Vue.js : la Vue.js Amsterdam 2023. J’ai eu l’honneur d’assister à la 5ème édition, couronnée par le retour d’Evan You, le créateur de Vue.js et Vite, en personne.

    Dans cette série de quatre articles, je vais vous faire revivre ces deux jours de conférences. En les lisant, vous aurez l’impression d’y avoir assisté !

    Cet article est le troisième des quatre, vous pourrez retrouver chaque partie de cette série ici :

    Dans cet article on va parler de Vue en 2023, de patterns Pinia, du futur de vue-router, de l’écosystème Vue et de TypeScript avec Vue.

    Beaucoup de sujets à traiter, alors, c’est parti !

    Photo de Louis GOURAIN auteur de l'article

    Louis GOURAIN

    Lire la suite
  • Couverture de l'article #2 - Nuxt.js, l'art de la composition, accessibilité : retour de la Vue.js Amsterdam 2023
    #2 - Nuxt.js, l'art de la composition, accessibilité : retour de la Vue.js Amsterdam 2023

    Il y a 4 ans

    Pour la première fois, Wanadev s’est rendu à la plus grosse conférence annuelle autour de Vue.js : la Vue.js Amsterdam 2023. J’ai eu l’honneur d’assister à la 5ème édition, couronnée par le retour d’Evan You, le créateur de Vue.js et Vite, en personne.

    Dans cette série de quatre articles, je vais vous faire revivre ces deux jours de conférences. En les lisant, vous aurez l’impression d’y avoir assisté !

    Cet article est le second des quatre, vous pourrez retrouver chaque partie de cette série ici :

    Dans cet article on va parler de Nuxt en 2023, d’un client Mastodon fait avec Nuxt, d’expérience développeur sur Nuxt, de Nitropack, de CSS-in-TS, de comment concevoir ses composants Vue.js, d’accessibilité et de maintenance d’écosystème open-source en entreprise.

    Beaucoup de sujets à traiter, alors c’est parti !

    Photo de Louis GOURAIN auteur de l'article

    Louis GOURAIN

    Lire la suite
  • Couverture de l'article #1 - NPM Package, PlayWright, Google LightHouse : retour de la Vue.js Amsterdam 2023
    #1 - NPM Package, PlayWright, Google LightHouse : retour de la Vue.js Amsterdam 2023

    Il y a 4 ans

    Pour la première fois, Wanadev s’est rendu à la plus grosse conférence annuelle autour de Vue.js : la Vue.js Amsterdam 2023. J’ai eu l’honneur d’assister à la 5ème édition, couronnée par le retour d’Evan You, le créateur de Vue.js et Vite, en personne.

    Dans cette série de quatre articles, je vais vous faire revivre ces deux jours de conférences. En les lisant, vous aurez l’impression d’y avoir assisté !

    Cet article est le premier des quatre, vous pourrez retrouver chaque partie de cette série ici :

    Dans cet article, nous allons parler de Rock’n Roll, voir comment créer son package NPM, découvrir PlayWright pour tester ses applications de bout en bout, parler de commerce international, déconstruire les idées reçues sur Google Lighthouse et aborder le sujet de la performance sous Vue.js.

    Beaucoup de sujets à traiter, alors c’est parti !

    Photo de Louis GOURAIN auteur de l'article

    Louis GOURAIN

    Lire la suite