Table des matières

Stockage de données

Documentation IndexedDB
Documentation localStorage
Documentation sessionStorage
Documentation React-redux
Documentation Redux Toolkit

Redux est une lib de gestion d'état global dans une application React. Cet état est stocké en mémoire mais disparaît lors d'un rechargement de page. Pour le rendre persistant, on peut l'associer aux mécanismes de stockage du navigateur:

Monter son Redux store

Le store Redux est l’objet qui contient l’état global. Pour le mettre en place, il faut utiliser Redux Toolkit:

// src/redux/reducers/sessionSlice.js

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
    data: JSON.parse(sessionStorage.getItem("session")) ?? null
};

const sessionSlice = createSlice({
    name: "session",
    initialState,
    reducers: {
        setSession(state, action) {
            const session = action.payload;
      
            state.data = session;
            sessionStorage.setItem("session", JSON.stringify(session));
        },
        unsetSession(state) {
            state.data = null;
            sessionStorage.removeItem("session");
        }
    },
});

export default sessionSlice.reducer;
export const { setSession, unsetSession } = sessionSlice.actions;
// src/redux/index.js

import sessionReducer from "./reducers/sessionSlice";

import { combineReducers } from "redux";
import { configureStore } from "@reduxjs/toolkit";

const rootReducer = combineReducers({
  session: sessionReducer
});

export const reduxStore = configureStore({ reducer: rootReducer });

Les actions du slice peuvent aussi être exportées dans l'index qui sert de point d'entrée du Redux store (facultatif).

export * from "./reducers/sessionSlice";
// src/components/app/ReduxProvider/index.jsx

import { Provider } from "react-redux";
import { reduxStore } from "../../../redux";

export const ReduxProvider = (props) => {
    const { children } = props;

    return (
        <Provider store={reduxStore}>
            {children}
        </Provider>
    );
};
// src/App.jsx

import { Router } from "./components/app/Router";
import { ReduxProvider } from "./components/app/ReduxProvider";

export const App = () => {
    return (
        <ReduxProvider>
            <Router />
        </ReduxProvider>
    );
};

Désormais l'état global de Redux est accessible dans n'importe quel fichier utilisé au sein du ReduxProvider .

Utiliser l'état global

Pour récupérer l'état global, react-redux met à disposition useSelector.

Maintenant que nous avons les moyens de savoir si une session est ouverte, reprenons nos composants PublicRoutes et PrivateRoutes et remplaçons cette condition “test”.

// src/components/app/Router/PublicRoutes/index.jsx

import { Outlet, Navigate } from "react-router-dom";
import { useSelector } from "react-redux";

export const PublicRoutes = () => {
    const session = useSelector(state => state.session.data);
    
    return session ? <Navigate to="/" : <Outlet />;        
};
// src/components/app/Routes/PrivateRoutes/index.jsx

import { Outlet, Navigate } from "react-router-dom";
import { useSelector } from "react-redux";

export const PrivateRoutes = () => {
    const session = useSelector(state => state.session.data);
    
    return session ? <Outlet /> : <Navigate to="/login" />;        
};

Nous sommes maintenant bloqués sur la page Login car aucune session n'est stockée (personne n'est authentifiée). .

Utiliser les actions

Reprenons à présent à présent notre requête de connexion et essayons de modifier l'état global avec les actions que nous avons ajoutées à notre slice. Pour cela il faut utiliser useDispatch.

// src/components/pages/Login/index.jsx

import { Input } from "../form/Input";
import { useDispatch } from "react-redux";
import { setSession } from "../../../redux";
import { API_URL } from "../../../utils/constants/vite";

export const Login = () => {
    const dispatch = useDispatch();
    
    const handleFormOnSubmit = (e) => {
        e.preventDefault() // empêche le comportement par défaut du formulaire
        
        const data = new FormData(e.target)
        const values = Object.fromEntries(data.entries());
        
        const request = {
            method: "POST",
            body: values,
            headers: {
                Accept: "application/json",
                "Content-Type": "application/json",
            }
        };

        fetch(`${API_URL}/login`, request)
            .then(response => response.json())
            .then(json => dispatch(setSession(json.data)))
            .catch(error => console.error(error));
    };
    
    return (
       // page login
    );
};

Et voilà vous maîtrisez la base de Redux. Il ne vous reste plus qu'à rajouter une fonction de déconnexion (dans votre page Home par exemple) et vous avez une application avec un système d'authentification fonctionnel.