Local Storage & State Management

contain

The Problem

When you refresh a webpage, everything resets:

  • User preferences lost
  • Form data gone
  • App state reset

How do we remember things?

Local Storage

What is Local Storage?

A way to store data in the browser

  • Data stays even after closing browser
  • Only accessible from same website
  • Stores strings only
  • ~5-10MB limit per domain

Think of it as a mini database in the browser!

Local Storage vs Cookies

Feature Local Storage Cookies
Size ~5-10MB ~4KB
Expires Never (until cleared) Can set expiration
Sent to server No Yes (every request)
Access JavaScript only JavaScript + Server

Use Local Storage for client-side data!

Using Local Storage

Basic Operations

// Save data
localStorage.setItem('username', 'Alice');

// Get data
const username = localStorage.getItem('username');
console.log(username); // 'Alice'

// Remove item
localStorage.removeItem('username');

// Clear everything
localStorage.clear();

Checking if Data Exists

const theme = localStorage.getItem('theme');

if (theme) {
  // Data exists
  applyTheme(theme);
} else {
  // No data saved yet
  applyTheme('light'); // Default
}

getItem() returns null if key doesn't exist!

Storing Objects

Local Storage only stores strings, but we can use JSON:

// Save an object
const user = { name: 'Alice', age: 20 };
localStorage.setItem('user', JSON.stringify(user));

// Get it back
const savedUser = localStorage.getItem('user');
const userObject = JSON.parse(savedUser);
console.log(userObject.name); // 'Alice'

Helper Functions

// Save any data type
function saveData(key, value) {
  localStorage.setItem(key, JSON.stringify(value));
}

// Load any data type
function loadData(key) {
  const item = localStorage.getItem(key);
  return item ? JSON.parse(item) : null;
}

// Usage
saveData('user', { name: 'Alice', age: 20 });
const user = loadData('user');

Common Use Cases

Use Case 1: Dark Mode Toggle

// Save user's preference
function setTheme(theme) {
  document.body.className = theme;
  localStorage.setItem('theme', theme);
}

// Load preference on page load
document.addEventListener('DOMContentLoaded', () => {
  const savedTheme = localStorage.getItem('theme') || 'light';
  document.body.className = savedTheme;
});

// Toggle button
function toggleTheme() {
  const current = document.body.className;
  const newTheme = current === 'light' ? 'dark' : 'light';
  setTheme(newTheme);
}

Use Case 2: Remember Form Data

// Save as user types
document.getElementById('email').addEventListener('input', (e) => {
  localStorage.setItem('email', e.target.value);
});

// Restore on page load
document.addEventListener('DOMContentLoaded', () => {
  const savedEmail = localStorage.getItem('email');
  if (savedEmail) {
    document.getElementById('email').value = savedEmail;
  }
});

Use Case 3: Shopping Cart

// Add item to cart
function addToCart(item) {
  const cart = loadData('cart') || [];
  cart.push(item);
  saveData('cart', cart);
  updateCartDisplay();
}

// Display cart
function updateCartDisplay() {
  const cart = loadData('cart') || [];
  const cartElement = document.getElementById('cart');
  cartElement.innerHTML = cart.map(item =>
    `<div>${item.name} - $${item.price}</div>`
  ).join('');
}

Use Case 4: To-Do List

let todos = loadData('todos') || [];

function addTodo(text) {
  todos.push({ text, done: false, id: Date.now() });
  saveData('todos', todos);
  renderTodos();
}

function toggleTodo(id) {
  todos = todos.map(todo =>
    todo.id === id ? { ...todo, done: !todo.done } : todo
  );
  saveData('todos', todos);
  renderTodos();
}

State Management

What is State?

State = the current condition of your app

Examples:

  • Is the user logged in?
  • What's in the shopping cart?
  • Is dark mode enabled?
  • What page are we on?

Managing State

// Simple state object
const state = {
  user: null,
  cart: [],
  theme: 'light',
  currentPage: 'home'
};

// Update state
function login(username) {
  state.user = username;
  updateUI();
}

function addToCart(item) {
  state.cart.push(item);
  saveToLocalStorage();
  updateUI();
}

State + Local Storage

Combine them for persistence:

// Load state from Local Storage
function loadState() {
  const saved = loadData('appState');
  if (saved) {
    Object.assign(state, saved);
  }
}

// Save state to Local Storage
function saveState() {
  saveData('appState', state);
}

// Initialize on page load
document.addEventListener('DOMContentLoaded', () => {
  loadState();
  renderApp();
});

Reactivity Pattern

Update UI automatically when state changes:

const state = {
  count: 0
};

function updateCount(newCount) {
  state.count = newCount;
  render(); // Re-render UI
  saveState(); // Save to Local Storage
}

function render() {
  document.getElementById('count').textContent = state.count;
}

Best Practices

1. Namespace Your Keys

Bad:

localStorage.setItem('theme', 'dark');
localStorage.setItem('user', 'Alice');

Better:

localStorage.setItem('myApp_theme', 'dark');
localStorage.setItem('myApp_user', 'Alice');

Avoids conflicts with other scripts!

2. Handle Errors

function saveData(key, value) {
  try {
    localStorage.setItem(key, JSON.stringify(value));
    return true;
  } catch (error) {
    // Storage full or disabled
    console.error('Failed to save:', error);
    return false;
  }
}

Users can disable Local Storage or storage might be full!

3. Don't Store Sensitive Data

Never store:

  • Passwords
  • Credit card numbers
  • API keys
  • Personal identification

Local Storage is NOT secure - anyone can read it!

4. Clean Old Data

// Remove old entries
function cleanupOldData() {
  const oneWeekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;

  for (let i = 0; i < localStorage.length; i++) {
    const key = localStorage.key(i);
    const item = loadData(key);

    if (item.timestamp < oneWeekAgo) {
      localStorage.removeItem(key);
    }
  }
}

5. Provide Defaults

function getTheme() {
  return localStorage.getItem('theme') || 'light'; // Default to light
}

function getTodos() {
  return loadData('todos') || []; // Default to empty array
}

Debugging Local Storage

View in DevTools

  1. Open Chrome DevTools (F12)
  2. Go to Application tab
  3. Click Local Storage in sidebar
  4. See all stored data

You can:

  • View keys and values
  • Edit values
  • Delete items
  • Clear all storage

Console Commands

// See all keys
for (let i = 0; i < localStorage.length; i++) {
  console.log(localStorage.key(i));
}

// See all data
console.log(localStorage);

// Clear everything
localStorage.clear();

When NOT to Use Local Storage

  1. Large files - use IndexedDB instead
  2. Frequently changing data - might be slow
  3. Sensitive information - security risk
  4. Cross-device sync - need backend database

Practice Ideas

  1. Settings panel - Save user preferences
  2. Note-taking app - Persist notes
  3. Game high scores - Remember best scores
  4. Recent searches - Show search history
  5. Custom themes - Let users customize colors

References