Aller au contenu
← 1001 Widgets
N° 038 · ●●○

Liste de tâches qui se souvient

Une liste de tâches sauvegardée dans le navigateur, avec des filtres et un compteur de ce qui reste. Le bon exercice pour enregistrer un tableau d'objets et le relire sans rien casser.

JS
Ce qu'on apprend
  • Enregistrer un tableau avec JSON.stringify
  • Relire des données sans planter si elles sont abîmées
  • Filtrer l'affichage sans toucher aux données
Pourquoi ce langage

Pourquoi une liste qui se souvient ? La liste de tâches de base oublie tout au rechargement. Ici, chaque changement est enregistré dans localStorage, et la liste revient telle quelle le lendemain.

localStorage ne garde que du texte : on transforme le tableau en JSON pour l'écrire, et on le relit avec JSON.parse. Si le contenu est abîmé ou absent, on repart d'une liste vide plutôt que de planter.

Les filtres ne modifient jamais les données : ils choisissent seulement ce qu'on affiche.

Pourquoi en JavaScript simple ? Une fonction changer qui modifie, sauvegarde et redessine : un seul chemin pour toutes les actions. Dans la démo, le cadre isolé bloque le stockage, la liste y vit en mémoire.

Comment ça marche
  1. LA CLÉ ET LA LECTURE

    Un JSON abîmé ou absent ne doit pas faire planter la page.

    const CLE = 'todo-memoire';
    function charger() {
      try {
        const v = JSON.parse(localStorage.getItem(CLE));
        return Array.isArray(v) ? v : [];
      } catch { return []; }
    }
    let taches = charger(), filtre = 'toutes';
  2. UN SEUL CHEMIN POUR CHANGER

    Modifier, sauvegarder, redessiner : toujours dans cet ordre.

    function changer(modifier) {
      modifier();
      try { localStorage.setItem(CLE, JSON.stringify(taches)); } catch { /* stockage bloqué */ }
      rendre();
    }
  3. LES ACTIONS

    const ajouter = texte => changer(() => taches.push({ id: Date.now(), texte, fait: false }));
    const cocher = (id, fait) => changer(() => { taches.find(t => t.id === id).fait = fait; });
    const supprimer = id => changer(() => { taches = taches.filter(t => t.id !== id); });
    const purger = () => changer(() => { taches = taches.filter(t => !t.fait); });
  4. FILTRER À L'AFFICHAGE

    Les données restent complètes, seul le rendu choisit.

    function visibles() {
      if (filtre === 'afaire') return taches.filter(t => !t.fait);
      if (filtre === 'faites') return taches.filter(t => t.fait);
      return taches;
    }
  5. D'UN ONGLET À L'AUTRE

    window.addEventListener('storage', e => {
      if (e.key === CLE) { taches = charger(); rendre(); }
    });
Pièges

PIÈGE 1 : Sauvegarder l'objet directement

Piège

Mauvais : localStorage.setItem('taches', taches). On enregistre le texte « [object Object] » et tout est perdu.

Fix

Correct : JSON.stringify à l'écriture, JSON.parse à la lecture.

PIÈGE 2 : Faire confiance à ce qu'on relit

Piège

Mauvais : JSON.parse sans try. Une ancienne version, une extension ou une modification à la main, et la page reste blanche.

Fix

Correct : un try et catch, puis vérifier que c'est bien un tableau avant de s'en servir.

PIÈGE 3 : Filtrer les données

Piège

Mauvais : taches = taches.filter(...) quand on clique sur « À faire ». En revenant à « Toutes », les tâches faites ont disparu.

Fix

Correct : filtrer une copie au moment de l'affichage, jamais l'état lui-même.

PERSONNALISER
  • Une date d'échéance par tâche, et les retards en tête de liste.
  • Le glisser-déposer pour réordonner, comme dans le tableau kanban.
  • La modification au double clic, avec Échap pour annuler.
OPTIMISATION
  • Ajoutez un numéro de version dans ce que vous enregistrez : le jour où le format change, vous saurez convertir les anciennes listes.
  • Pour des milliers d'éléments ou des fichiers, passez à IndexedDB, plus adapté que localStorage.
VERS REACT

Le tableau vit dans un useState initialisé avec une fonction : useState(charger), pour ne lire qu'une fois.

Un useEffect sur taches écrit dans localStorage à chaque changement.

Le filtre est un autre useState, et la liste visible se calcule au rendu.

Commentaires
0/1000

Chargement des commentaires…