13

LocalStorage

Persistance des données

Le Web Storage API fournit des mécanismes de stockage côté client : localStorage (persistant) et sessionStorage (temporaire). Essentiel pour sauvegarder des préférences utilisateur et des données hors ligne.

📦 localStorage vs sessionStorage

Caractéristique localStorage sessionStorage
Persistance ✅ Permanent (jusqu'à suppression manuelle) ⏱️ Temporaire (fin de session)
Portée Partagé entre tous les onglets du domaine Isolé par onglet
Capacité ~5-10 MB (selon navigateur) ~5-10 MB (selon navigateur)
Cas d'usage Préférences, thème, cache Formulaires multi-étapes, panier temporaire

🔧 Opérations de Base

// CRÉER / MODIFIER
localStorage.setItem("username", "Alice");
sessionStorage.setItem("tempData", "xyz");

// LIRE
const user = localStorage.getItem("username");  // "Alice"
const temp = sessionStorage.getItem("tempData"); // "xyz"

// SUPPRIMER UNE CLÉ
localStorage.removeItem("username");

// TOUT SUPPRIMER
localStorage.clear();
sessionStorage.clear();

// VÉRIFIER L'EXISTENCE
if (localStorage.getItem("theme")) {
    // La clé existe
}

// NOMBRE D'ÉLÉMENTS
console.log(localStorage.length);  // 0, 1, 2...

// ACCÉDER PAR INDEX
const key = localStorage.key(0);  // Nom de la 1ère clé
const value = localStorage.getItem(key);

📋 Stocker des Objets (JSON)

// ❌ ERREUR FRÉQUENTE : Stocker directement un objet
const user = { name: "Alice", age: 25 };
localStorage.setItem("user", user);
// Stocke "[object Object]" → INUTILISABLE !

// ✅ SOLUTION : Sérialiser avec JSON.stringify
localStorage.setItem("user", JSON.stringify(user));

// RÉCUPÉRATION : Désérialiser avec JSON.parse
const savedUser = localStorage.getItem("user");
const parsedUser = savedUser ? JSON.parse(savedUser) : null;

// PATTERN : Helper Functions
const storage = {
    set(key, value) {
        localStorage.setItem(key, JSON.stringify(value));
    },
    get(key, defaultValue = null) {
        const item = localStorage.getItem(key);
        try {
            return item ? JSON.parse(item) : defaultValue;
        } catch {
            return defaultValue;
        }
    },
    remove(key) {
        localStorage.removeItem(key);
    }
};

// Usage
storage.set("config", { theme: "dark", lang: "fr" });
const config = storage.get("config", { theme: "light", lang: "en" });

💼 Cas d'Usage Pratiques

// 1. THÈME DARK/LIGHT PERSISTANT
function saveTheme(theme) {
    localStorage.setItem("theme", theme);
    document.body.className = theme;
}

function loadTheme() {
    const theme = localStorage.getItem("theme") || "light";
    document.body.className = theme;
}

// Au chargement de la page
loadTheme();

// 2. FORMULAIRE MULTI-ÉTAPES (sessionStorage)
function saveDraft() {
    const formData = {
        step1: { name: document.getElementById("name").value },
        step2: { email: document.getElementById("email").value }
    };
    sessionStorage.setItem("formDraft", JSON.stringify(formData));
}

function loadDraft() {
    const draft = sessionStorage.getItem("formDraft");
    if (draft) {
        const data = JSON.parse(draft);
        // Remplir les champs
    }
}

// 3. HISTORIQUE D'ACTIONS (avec limite)
function addToHistory(action) {
    const history = JSON.parse(localStorage.getItem("history") || "[]");
    history.unshift(action);  // Ajouter au début
    
    // Limiter à 10 dernières actions
    if (history.length > 10) history.pop();
    
    localStorage.setItem("history", JSON.stringify(history));
}

// 4. CACHE AVEC EXPIRATION
function cacheWithExpiry(key, value, ttlMinutes) {
    const item = {
        value: value,
        expiry: Date.now() + (ttlMinutes * 60 * 1000)
    };
    localStorage.setItem(key, JSON.stringify(item));
}

function getCachedItem(key) {
    const itemStr = localStorage.getItem(key);
    if (!itemStr) return null;
    
    const item = JSON.parse(itemStr);
    if (Date.now() > item.expiry) {
        localStorage.removeItem(key);
        return null;
    }
    return item.value;
}

🎮 Playground Storage

Testez localStorage en temps réel. Les données persisteront même après rechargement de la page.

Sélectionnez une action

📡 Storage Event (Synchronisation entre onglets)

// Écouter les changements de localStorage dans AUTRES onglets
window.addEventListener('storage', (e) => {
    console.log('Clé modifiée:', e.key);
    console.log('Ancienne valeur:', e.oldValue);
    console.log('Nouvelle valeur:', e.newValue);
    console.log('URL:', e.url);
    
    // Exemple : Synchroniser le thème
    if (e.key === 'theme') {
        document.body.className = e.newValue;
    }
});

// ⚠️ ATTENTION : L'événement ne se déclenche PAS dans l'onglet qui a modifié le storage
// Il ne se déclenche que dans les AUTRES onglets du même domaine
Best Practice : Créez des helpers pour sérialiser/désérialiser automatiquement. Utilisez try/catch lors du parsing JSON pour éviter les erreurs. Préfixez vos clés (ex: app_theme) pour éviter les conflits. Utilisez sessionStorage pour les données sensibles temporaires.
⚠️ Sécurité : Ne stockez JAMAIS de mots de passe, tokens d'authentification ou données sensibles dans localStorage ou sessionStorage. Ces storages sont vulnérables aux attaques XSS (Cross-Site Scripting). Pour l'authentification, utilisez des cookies HttpOnly et Secure.
⚠️ Limites : Les données sont stockées en tant que strings uniquement. La capacité est limitée (~5-10MB). Les opérations sont synchrones et peuvent bloquer le thread. Pour de grandes quantités de données, utilisez IndexedDB.
← Fetch Suivant: Spread/Rest →