Wat is localStorage?

localStorage is een manier om data op te slaan in de browser van de gebruiker. Deze data blijft bewaard, zelfs als:

  • De gebruiker de browser sluit
  • De computer wordt herstart
  • De internetverbinding wegvalt

Gebruik localStorage voor:

  • Gebruikersvoorkeuren (dark mode, taal)
  • Winkelwagen bijhouden
  • Formulier data tijdelijk opslaan
  • Inloggegevens (niet wachtwoorden!)

Niet geschikt voor:

  • Gevoelige data (wachtwoorden, creditcards)
  • Grote hoeveelheden data (>5MB)
  • Data die gedeeld moet worden tussen gebruikers

Basis localStorage Gebruik

Data Opslaan

// String opslaan
localStorage.setItem('username', 'Jan');

// Number opslaan (wordt automatisch string)
localStorage.setItem('age', '25');

// Object opslaan (moet eerst naar JSON)
const user = { name: 'Jan', age: 25 };
localStorage.setItem('user', JSON.stringify(user));

Data Ophalen

// String ophalen
const username = localStorage.getItem('username');
console.log(username); // 'Jan'

// Object ophalen (moet terug naar object)
const userString = localStorage.getItem('user');
const user = JSON.parse(userString);
console.log(user.name); // 'Jan'

Data Verwijderen

// Eén item verwijderen
localStorage.removeItem('username');

// Alles verwijderen
localStorage.clear();

Onthoud:

  • setItem(key, value) - Opslaan
  • getItem(key) - Ophalen
  • removeItem(key) - Verwijderen
  • clear() - Alles wissen

localStorage met React State

Simpel Voorbeeld: Username Opslaan

import { useState, useEffect } from 'react';

const UserGreeting = () => {
  const [name, setName] = useState('');

  // Laden van localStorage bij mount
  useEffect(() => {
    const savedName = localStorage.getItem('username');
    if (savedName) {
      setName(savedName);
    }
  }, []);

  // Opslaan in localStorage bij wijziging
  const handleSave = () => {
    localStorage.setItem('username', name);
    alert('Naam opgeslagen!');
  };

  return (
    <div>
      <input 
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Typ je naam"
      />
      <button onClick={handleSave}>Opslaan</button>
      <p>Hallo, {name}!</p>
    </div>
  );
};

Automatisch Synchroniseren

import { useState, useEffect } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);

  // Laden bij mount
  useEffect(() => {
    const savedCount = localStorage.getItem('count');
    if (savedCount) {
      setCount(Number(savedCount));
    }
  }, []);

  // Opslaan bij elke wijziging
  useEffect(() => {
    localStorage.setItem('count', count);
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
};

Praktische Voorbeelden

Todo List met localStorage

import { useState, useEffect } from 'react';

const TodoList = () => {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');

  // Laden bij mount
  useEffect(() => {
    const savedTodos = localStorage.getItem('todos');
    if (savedTodos) {
      setTodos(JSON.parse(savedTodos));
    }
  }, []);

  // Opslaan bij wijziging
  useEffect(() => {
    localStorage.setItem('todos', JSON.stringify(todos));
  }, [todos]);

  const addTodo = () => {
    setTodos([...todos, { id: Date.now(), text: input }]);
    setInput('');
  };

  return (
    <div>
      <input 
        value={input}
        onChange={(e) => setInput(e.target.value)}
      />
      <button onClick={addTodo}>Add</button>
      
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>{todo.text}</li>
        ))}
      </ul>
    </div>
  );
};

Dark Mode Toggle

import { useState, useEffect } from 'react';

const DarkModeToggle = () => {
  const [isDark, setIsDark] = useState(false);

  useEffect(() => {
    const savedMode = localStorage.getItem('darkMode');
    if (savedMode === 'true') {
      setIsDark(true);
      document.body.classList.add('dark-mode');
    }
  }, []);

  const toggleMode = () => {
    const newMode = !isDark;
    setIsDark(newMode);
    localStorage.setItem('darkMode', newMode);
    
    if (newMode) {
      document.body.classList.add('dark-mode');
    } else {
      document.body.classList.remove('dark-mode');
    }
  };

  return (
    <button onClick={toggleMode}>
      {isDark ? 'Light Mode' : 'Dark Mode'}
    </button>
  );
};

Custom Hook voor localStorage

// useLocalStorage.js
import { useState, useEffect } from 'react';

const useLocalStorage = (key, initialValue) => {
  const [value, setValue] = useState(() => {
    const saved = localStorage.getItem(key);
    return saved ? JSON.parse(saved) : initialValue;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
};

export default useLocalStorage;

// Gebruik:
const Counter = () => {
  const [count, setCount] = useLocalStorage('count', 0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
};

Tips & Limitaties

  • Max 5-10MB per website - Niet voor grote data
  • Alleen strings - Gebruik JSON.stringify/parse voor objecten
  • Synchronous - Kan de UI blokkeren bij grote data
  • Per domein - Kan niet gedeeld worden tussen websites
  • Niet beveiligd - Gebruiker kan het zien en aanpassen

Veelgemaakte Fouten

Fout - Object zonder JSON.stringify:

const user = { name: 'Jan' };
localStorage.setItem('user', user);
// Slaat op als "[object Object]"

Goed - Met JSON.stringify:

localStorage.setItem('user', JSON.stringify(user));

Fout - Vergeten te checken of item bestaat:

const user = JSON.parse(localStorage.getItem('user'));
// Crasht als 'user' niet bestaat!

Goed - Check eerst:

const userString = localStorage.getItem('user');
const user = userString ? JSON.parse(userString) : null;