• 8 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 31/01/2024

Ajoutez Redux à une application React

Créez une application React

Redux fonctionne indépendamment de React. Nous avons découvert précédemment les concepts qui fondent son fonctionnement. Nous savons ainsi que nous pouvons : 

  • stocker dans un store centralisé des états ;

  • exécuter des parties de notre code en fonction des changements intervenant dans le store ;

  • modifier les valeurs du store en appliquant des actions. 

Créons alors notre application React. Pour ce faire, vous pouvez vous référer au cours Débutez avec React, ou suivre les commandes ci-dessous :

## create react project
npm init react-app resto-cmd
# ou
yarn react-app resto-cmd
# ou encore
npx create-react-app resto-cmd

Nous allons ajouter notre package Redux Toolkit pour bénéficier de Redux dans notre application React et du package react-redux  , qui va nous permettre de manipuler le store dans nos composants :

Pour ce faire, utilisez la commande suivante :

## add rtk as package
npm install @reduxjs/toolkit react-redux
# ou
yarn add @reduxjs/toolkit react-redux

À ce stade, vous devriez obtenir une application React prête à être développée avec notre state manager Redux.

Afin de préparer la suite de nos avancées, nous allons utiliser une partie du code que nous avons déjà implémenté !

Afin de suivre les bonnes pratiques, nous allons respecter certaines règles proposées dans le guide de styles que vous retrouvez dans la documentation de Redux (en anglais).

  1. D’abord, créons un dossier app/  .

  2. Nous y déplaçons nos fichiers App.js  et App.css  en modifiant leurs imports.

  3. Ensuite, nous créons notre fichier app/store.js  .

  4. Créons un dossier common  pour y placer notre fichier models.js  , car il sera utile à plusieurs parties de notre application et tous les composants réutilisables. Nous ajoutons nos produits dans ce fichier.

  5. Puis, en copiant l’intégralité de notre fichier flux_s6.js  ,  nous ajoutons ce code dans le fichier store.js  . J'en profite pour rajouter deux produits par défaut dans mon store. Vous pouvez voir dans le code qui suit comment je m’y prends.

  6. Nous modifions notre import du composant App dans  index.js  qui devient  ./app/App.js  .

  7. Nous ajoutons le provider dans notre fichier app/App.js  comme suit, et nettoyons un peu son implémentation :

import { Provider } from 'react-redux'
import { store } from './store';
import './App.css';

function App() {
 return (
    <Provider store={store}>
        <div className="App">
        </div>
    </Provider>
 );
}

export default App;

Vous pouvez suivre le screencast suivant pour comprendre comment je m’y prends :

Vous devriez à ce stade avoir :

1. Un fichier app/store.js  comme suit :

import { configureStore } from "@reduxjs/toolkit"
import { PouletCroquant, SuperCremeux } from "../common/models";


let state = {
    value: null,
    list: [
        SuperCremeux,
        PouletCroquant,
    ]
};

const reducer = (currentState, action ) => {
    switch (action.type) {
        case 'ADD_PRODUCT':
            const listWithNewProduct = [...currentState.list, action.payload]
            return {...currentState, list: listWithNewProduct}
        case 'REMOVE_PRODUCT':
            const list = currentState.list.filter(
                (item, index) => index !== action.payload
            )
            return {...currentState, list: list}
        case 'APPLY_VOUCHER':
            const withVoucherList = currentState.list.map(
                        item => item.title === 'Super Crémeux' ? ({...item, price: action.payload.price}) : item
            )
            return {...currentState, list: withVoucherList}

        case 'UPDATE_FIRSTNAME':
            const owner = {...currentState.owner, firstName: action.payload}
            return {...currentState, owner}
        default:
            return currentState
    }
}

export const store = configureStore(
    {
        preloadedState: state,
        reducer
    }
)

2. Un fichier common/models.js  :

export const DoubleCantal = {
    title: 'Double Cantal',
    price: 15.99,
}

export const SuperCremeux = {
    title: 'Super Crémeux',
    price: 14.99,
}

export const PouletCroquant = {
    title: 'Poulet Croquant',
    price: 17.99,
}

3. Un fichier app/App.js  :

import { Provider } from 'react-redux'
import { store } from './store';
import './App.css';

 
function App() {
 return (
    <Provider store={store}>
        <div className="App">
        </div>
    </Provider>
 );
}

export default App;

Nous venons d’intégrer nos sources à notre projet React. Ainsi, nous avons :

  • construit un fichier store.js  pour y placer notre reducer et notre configuration du store ;

  • appliqué notre provider à la racine de notre application ( App.js  ) afin de pouvoir accéder à notre store au sein de chacun de nos composants ;

  • placé nos modèles dans un fichier dédié pour mieux structurer notre code ;

  • ajouté le style de l’application pour utiliser les classes toutes prêtes.

Et voilà, nous sommes enfin prêts à manipuler notre state dans React avec Redux et Redux ToolKit !

Associez le store à un premier composant

Maintenant que notre store est configuré, notre prochain défi sera de…

… l’associer à l’un de nos composants ?

Exact !

Pour accéder au store de Redux dans nos composants, nous pouvons utiliser le hook useStore  de react-redux que nous avons précédemment installé.

Ci-dessous, un exemple d’implémentation permettant d’accéder au store.

import { useStore } from "react-redux";

const Component = () => {
    const store = useStore();
    return <i></i>
};

useStore  nous permet donc d’accéder à l’instance du store qui est diffusée dans notre application via le Provider préalablement inséré.

Maintenant que nous savons comment accéder au store, nous allons commencer à l’utiliser dans notre application.

Pour cela, nous allons créer notre composant affichant la liste des produits sélectionnés, que nous appellerons Cart  , dans le fichier features/cart/Cart.js  .

L’instance store  fournit une méthode getState()  qui nous permet d’obtenir à chaque instance les valeurs stockées dans le store. Si nous faisons donc appel à store.getState()  , nous aurons accès à list  qui contient notre liste de produits sélectionnés.

Il ne nous reste donc plus qu’à “mapper” sur store.getState().list  en faisant :

store.getState().list.map((item, index) => <JSXElement />

Je vous propose de suivre le screencast suivant pour comprendre comment le créer.

Nous venons donc d’ajouter l’affichage du listing de nos produits sélectionnés dans notre panier.

Faisons le point sur cette phase d’implémentation, au cours de laquelle nous avons :

  1. Déclaré et inséré notre composant Cart dans App.js  .

  2. Créé notre composant Cart dans Cart.js  .

  3. Importé useStore  de react-redux.

  4. Utilisé useStore  pour l’assigner à notre variable locale store.

  5. Utilisé la méthode getState  pour récupérer l’état (le state) courant.

  6. Mappé sur list du store qui contient la liste des produits sélectionnés.

Ce qui nous donne un fichier  app/App.js  :

import { Provider } from 'react-redux'
import { store } from './store';
import './App.css';
import { Cart } from '.features/cart/Cart';


function App() {
 return (
   <Provider store={store}>
     <div className="App">
       <Cart />
     </div>
   </Provider>
 );
}


export default App;

Ainsi qu'un fichier  features/cart/Cart.js  :

import { useStore } from "react-redux";

export const Cart = () => {
   const store = useStore();


   return <div className="Selection">
       <h1>Liste de produits sélectionnés</h1>
       {
           store.getState().list.map(
        	(item, index) => <span key={index} className="SelectedProduct">{item.title} {item.price} €</span>
           )
       }
   </div>
};

Faites des modifications du store à partir de votre votre composant

Nous voilà capables d’afficher la liste de produits sélectionnés… enfin, presque ! La liste contient des produits insérés manuellement avec le code.

Mais nous souhaitons rendre cette liste dynamique, c'est-à-dire être capables d’ajouter d'autres produits sans pour cela réécrire de code pour en ajouter.

Pour ajouter cette fonctionnalité, nous allons créer un bouton pour chaque produit et utiliser le store pour stocker le produit correspondant à chaque bouton lors du clic sur le bouton.

À l’instar de la méthode getState  , l’instance store  fournit une méthode dispatch qui va nous permettre d’appliquer des actions, dispatch()  .

Bien évidemment, la méthode dispatch fonctionne de pair avec la méthode subscribe. On va donc modifier notre accès à list  et ajouter un état local qui sera modifié à chaque dispatch  .

On ajoute donc :

const [list, setList] = useState(store.getState().list);

Et afin de venir modifier notre state à chaque changement du store, on ajoute à notre composant :

useEffect(() => {
store.subscribe(() => { setList(store.getState().list) })
}, [store])

Pour ajouter un produit, nous allons créer un bouton et ajouter un dispatch  de type ADD_PRODUCT  avec comme payload le modèle  ‘SuperCremeux’  au clic sur celui-ci :

<div className="CartNavBar">
<button onClick={() => store.dispatch({type: 'ADD_PRODUCT', payload: SuperCremeux})}>Ajouter un super crémeux</button>
</div>

Je vous propose de suivre le screencast suivant pour bien comprendre :

Revoyons ensemble ce que nous venons de réaliser :

  1. Nous avons connecté notre composant au store pour écouter chaque changement de valeur de celui-ci.

  2. Nous avons exécuté une action d’ajout de produit pour modifier la valeur du store.

Ce qui nous donne dans notre fichier  features/cart/Cart.js  :

import { useStore } from "react-redux";
import { SuperCremeux } from "./models";
import { useEffect, useState } from "react";


export const Cart = () => {
    const store = useStore();
    const [list, setList] = useState(store.getState().list)

    useEffect(() => {
        store.subscribe(() => setList(store.getState().list))
    })

    return <div className="Selection">
        <h1>Choisir son menu</h1>
        <div className="CartNavBar">
                <button onClick={() => store.dispatch({type: 'ADD_PRODUCT', payload: SuperCremeux})}>Ajouter un super crémeux</button>
        </div>
        {
        list.map((item, index) => <span key={index} className="SelectedProduct">{item.title} {item.price} €</span>
            )
        }
    </div>
};

Débuggez votre configuration Redux

Avant d’aller plus loin, je vous propose de vous mettre dans les meilleures conditions pour travailler avec Redux et Redux ToolKit.

En tant qu’utilisateur régulier de React, vous avez sans doute eu l’opportunité d’installer les DevTools, ces outils qui permettent de visualiser et de débugger votre application React dans la barre d’inspection du navigateur.

Eh bien Redux fournit ce même genre d’outil, Redux DevTools !

La fenêtre Redux DevTools vous permet de débugger Redux, comme les DevTools vous permet de débugger React
Redux DevTools

Découvrons l’outil Redux DevTools :

Nous avons vu que cet outil nous sera utile pour débugger notre application Redux, notamment grâce à la possibilité de suivre les changements du state, de visualiser les actions et leur contenu, la possibilité de rejouer, d’éditer des actions et encore plein d’autres fonctionnalités.

Vous savez à présent comment l’installer et l’utiliser. Il vous sera très utile pour déboguer votre application.

À vous de jouer

Nous voilà maintenant capables de modifier les valeurs de notre store via notre composant. Je vous propose un petit exercice pour continuer à mettre en pratique ce que nous savons faire.

Pour cela, nous allons afficher le montant total de la commande dans notre composant  Cart.js  et remplir le besoin suivant :

En tant qu’utilisateur,

  • tant qu’il n’y a pas de produit dans ma sélection, je peux voir indiquée la mention : “Aucun produit sélectionné pour le moment” ;

  • lorsque le nombre de produits est supérieur à 0, je peux voir indiquée la somme des prix des produits sélectionnés sous la forme : “Total commande X euros”.

Pour tester que l’on affiche bien le message “Aucun produit sélectionné pour le moment”, n’oubliez pas de retirer les produits par défaut du store.

Une fois que vous avez ajouté tout ça, suivez-moi dans le screencast ci-dessous pour voir la correction :

En résumé

  • Pour utiliser Redux dans React, il nous faut utiliser useStore  de react-redux.

  • Nous pouvons utiliser les mêmes outils, le dispatch  et le subscribe  , pour écouter et modifier les valeurs du store.      

  • Redux peut être utilisé avec des outils qui facilitent le développement, Redux DevTools.

Nous avons déjà créé un composant qui permet l’utilisation de notre state managé. Allons plus loin, avec d’autres composants et en utilisant plus d’outils fournis par Redux Toolkit et react-redux.

Exemple de certificat de réussite
Exemple de certificat de réussite