• 15 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 01/12/2023

Appliquez Redux dans une app React

Dans la partie 1 nous avons découvert Redux. Il nous a permis de mieux organiser la logique de Tennis Score grâce à un système en trois parties : state, actions et reducer.

Nous avons également vu le store qui permet de lier ces éléments et de les faire fonctionner ensemble. C’est déjà bien, mais là où Redux dévoile tout son potentiel, c’est lorsqu’il est utilisé avec React !

Découvrez et installez React-Redux

Vous pouvez retrouver le code de Tennis Score sur GitHub : Repository Redux Tennis Score.

Pour faire fonctionner Redux avec React, nous allons avoir besoin d’une librairie pour faire le pont entre les deux : React-Redux.

On est obligé de passer par React-Redux ?

Non, ce n’est pas obligé. Il est possible de faire fonctionner React et Redux ensemble sans aucune autre librairie. Par exemple, on pourrait appeler ReactDOM.render()  dans le store.subscribe()  de Redux. Cependant, cela ne serait pas très pratique et cela pourrait poser des problèmes de performance, bref, je ne vous le recommande pas du tout.

React-Redux apporte des outils adaptés pour interagir avec Redux depuis React, ce qui explique sa popularité. Aujourd’hui l’usage de React-Redux est tellement une évidence que bien souvent “Redux” veut en réalité dire “Redux et React-Redux”. C’est d’ailleurs assez évident si l’on compare le nombre de téléchargements des deux librairies, selon NPM Trends :

Le graphique montre le nombre de téléchargements comparé entre Redux et React-Redux
Nombre de téléchargements comparé entre Redux et React-Redux

Il va ensuite falloir installer Redux et React-Redux avec Yarn et importer le code Redux de la partie précédente (state, actions, reducer et store). Il faudra alors modifier la manière dont on importe Redux :

// au lieu d'importer depuis une url...
import { createStore } from "https://cdn.skypack.dev/redux@4.0.5";
// on import redux depuis le dossier `node_modules`
import { createStore } from 'redux';

Vous pouvez retrouver le code de ce screencast sur la branche P2C1-base du repository.

Nous sommes maintenant prêts à créer des composants, et surtout à les connecter à Redux grâce à React-Redux !

Envoyez des actions depuis vos composants avec useDispatch

Pour interagir avec Redux, React-Redux utilise des custom hooks. Ça vous parle ? C’est normal, vous en avez probablement déjà manipulé ! Si vous avez suivi le cours Créez une application React complète, vous en avez même créé 2useFetch  et useDarkMode  .

Voici tout de même un petit rappel pour vous rafraîchir la mémoire :

  • React expose un certain nombre de hooks “primitifs” tels que useState  ou useEffect  . Ces hooks doivent être appelés dans les composants fonctions en respectant la règle des hooks, comme écrit dans la documentation React (en français).

  • Les custom hooks sont des hooks écrits par les développeurs, qui permettent de créer des morceaux de logique réutilisables, en combinant d’autres hooks ensemble.

export function useFetch(url) {
    const [data, setData] = useState({})
    const [isLoading, setLoading] = useState(true)
    const [error, setError] = useState(false)
    useEffect(() => {
        if (!url) return
        setLoading(true)
        async function fetchData() {
            try {
                const response = await fetch(url)
                const data = await response.json()
                setData(data)
            } catch (err) {
                console.log(gerr)
                setError(true)
            } finally {
                setLoading(false)
            }
        }
        fetchData()
    }, [url])
    return { isLoading, data, error }
}

C’est grâce à des custom hooks exposés par React-Redux que nous allons interagir avec Redux depuis nos composants React.

// (a) on import useDispatch depuis react-redux
import { useDispatch } from 'react-redux';
 
export function PlayPauseButton() {
  // (b) on utilise le hooks useDispatch dans notre composant
  // pour récupérer la fonction dispatch de redux
  const dispatch = useDispatch();
 
  return <button onClick={() => {
    // (c) au clique sur le bouton on exécute la fonction 
    // dispatch avec une action.
    dispatch({ type: "playPause" })
  }} >Pause / Reprendre</button>
}

Dans l’extrait de code ci-dessus :

(a) On importe depuis react-redux  la fonction useDispatch  . On peut facilement reconnaître que cette fonction est un hook, car son nom commence par use  .

(b) Lorsque l’on utilise ce hook dans notre composant, il ne prend aucun paramètre et retourne la fonction dispatch  de notre store Redux.

(c) On peut ensuite utiliser la fonction dispatch  dans notre composant. Dans le cas ci-dessus, on l’utilise lorsque l'utilisateur clique sur le bouton pour mettre en pause ou reprendre la partie.

C’est bien beau de pouvoir changer le state, mais pour vérifier qu’il a bien changé, il va d’abord falloir l’afficher dans React. Pour faire cela, nous allons utiliser un second hook :useSelector .

Utilisez le state dans les composants avec useSelector

Pour utiliser le state de Redux dans nos composants, nous allons utiliser le hook useSelector de React-Redux.

Lorsque l’on utilise useSelector  , il faut lui passer une fonction en argument. On appelle cette fonction un selector. Ce selector va recevoir le state en argument et doit retourner une partie de ce state.

Dans l'exemple suivant, on utilise useSelector  pour extraire la propriété playing  du state :

// on import useSelector depuis react-redux
import { useSelector } from "react-redux";
 
export function Display() {
  // on utilise useSelector avec en paramètre une fonction
  // qui permet de récupérer uniquement la propriété `playing`
  // du state
  const gameIsPlaying = useSelector((state) => state.playing);
  // on peut ensuite utiliser cette valeur dans le rendu
  return <p>{gameIsPlaying ? "Jeu en cours" : "C'est la pause"}</p>;
}

Pourquoi on ne fait pas juste store.getState()  comme dans la partie 1 ?

Parce que useSelector  fait plus que simplement lire les données du state ! En effet, avec useSelector  , notre composant va être automatiquement mis à jour lorsque le state change.

Comment fait useSelector  pour savoir que le state a changé ?

C’est vrai ça, si seulement on avait un moyen de savoir quand le state de Redux change… 😏 Eh oui ! C’est grâce à store.subscribe()  que useSelector  détecte les modifications de notre state Redux.

Mais ce n’est pas tout ! Lors d’un changement de state, useSelector  va utiliser la fonction de selector (  (state) => state.playing   dans l'exemple ci-dessus) pour vérifier si le morceau de state sélectionné a changé ou non.

Grâce à ce système, notre composant va être mis à jour uniquement si le state qu’il utilise change. Grâce à ce système, notre application va être automatiquement optimisée !

Branchez le store Redux à React avec le Provider

Nous allons maintenant utiliser nos deux composants PlayPauseButton  et  Display  dans notre application React. On importe donc ces deux composants et on les utilise dans le retour du composant App  :

import { PlayPauseButton } from "./PlayPauseButton";
import { Display } from "./Display";
 
export default function App() {
    return (
        <div>
            <Display />
            <PlayPauseButton />
        </div>
    );
}

On vient d’organiser notre application un peu comme le schéma ci-dessous :

L’application React se connecte à React-Redux avec useDispatch et useSelector
Nos composants sont connectés à Redux via les hooks de React-Redux

Il ne reste plus qu'à lancer l’application avec  yarn start   et… ça ne fonctionne pas ! 🤔

Erreur d’accès de React-Redux au store, car le composant Provider est manquant
Erreur d’accès de React-Redux au store

Le problème ici c’est que React-Redux n'a pas accès à notre store. Pour résoudre cela, Il va falloir utiliser un composant exposé par React-Redux : le Provider.

C’est grâce au Provider que useDispatch  et useSelector  auront accès à votre store. Le Provider doit englober toute votre application et attend une prop store  : votre store Redux.

On va donc modifier le fichier index.js  :

import { StrictMode } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
// on importe le Provider
import { Provider } from "react-redux";
// on importe le store
import { store } from "./store";
 
import App from "./App";
 
const rootElement = document.getElementById("root");
ReactDOM.render(
    // Le Provider doit englober toute l'application !
    <Provider store={store}>
        <StrictMode>
            <App />
        </StrictMode>
    </Provider>,
    rootElement
);
Le Provider englobe toute l’application React pour se connecter au Store et accéder à Redux
Le Provider englobe toute l’application React

Cela devrait fonctionner maintenant !

 Vous pouvez retrouver le code de ce screencast sur la branche P2C1-provider du repository.

Exercez-vous

On parle, on parle mais si on passait à la pratique !

Cette fois je ne vous donne pas de projet de départ, c’est à vous d’initialiser le projet ! Ici, vous allez reprendre Tennis Score et le transformer en application React-Redux.

Voici les différentes étapes à réaliser :

  • Initialiser un projet avec Create-React-App.

  • Installer Redux et React-Redux avec Yarn.

  • Reprendre le state, les actions et le reducer du chapitre précédent.

  • Copier le CSS du chapitre précédent.

  • Mettre en place le Provider de React-Redux.

  • Déplacer les action creators dans un fichier actions.js  .

  • Créer des composants pour l’affichage.

  • Utiliser useSelector  et useDispatch  pour connecter vos composants à votre store Redux.

Vous ne savez pas par où commencer ? Pas de panique, les screencasts de ce chapitre vous montrent les premières étapes.

Une fois que vous avez terminé, allez jeter un œil à la version corrigée sur la branche P2C1-solution du repository.

En résumé

Pour utiliser React et Redux ensemble de manière efficace, on utilise une librairie tierce : React-Redux.

Pour utiliser React-Redux, il faut :

  • Envoyer le store grâce au Provider qui englobe toute l’application.

  • Utiliser useDispatch  pour envoyer des actions depuis les composants.

  • Utiliser useSelector  pour extraire des morceaux de state et mettre à jour le composant en cas de changement de state.

Maintenant que nous avons une application React-Redux qui fonctionne, allons plus loin dans le state management ! Dans le prochain chapitre, nous verrons comment rendre la manipulation du state plus facile – je vous y retrouve tout de suite !

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