Todo List State Management

mediumTypeScript

Lesson

State Management with Classes and Arrays

Managing state in applications is fundamentally about tracking data that changes over time. When building interactive features like todo lists, shopping carts, or user profiles, you need to store data in memory and provide methods to create, read, update, and delete that data.

In TypeScript, classes provide an excellent way to encapsulate state management logic. By keeping data private and exposing controlled methods for manipulation, you create a clean interface that prevents external code from corrupting your state.

Arrays are perfect for managing collections of similar items. They provide built-in methods like push(), filter(), and find() that make common operations straightforward. The key is understanding when to mutate arrays directly versus creating new ones.

For unique identifiers, a simple counter pattern works well for in-memory data. Each new item gets the next sequential number, ensuring no duplicates. In real applications, you might use UUIDs or database-generated IDs instead.

When designing state management classes, think about the operations users need: adding items, removing items, updating items, and querying items. Each method should have a single responsibility and return meaningful values (like the created item or a boolean indicating success).

Error handling is crucial too. Instead of throwing errors for missing items, return false or empty arrays. This makes your API more predictable and easier to use in UI code where missing items are common.

The immutability principle suggests returning copies of internal data rather than direct references. This prevents external code from accidentally modifying your internal state, which could lead to bugs that are hard to track down.

Example
1class BookLibrary { 2 private books: Book[] = []; 3 private nextId = 1; 4 5 addBook(title: string, author: string): Book { 6 const book = { 7 id: this.nextId++, 8 title, 9 author, 10 isCheckedOut: false 11 }; 12 this.books.push(book); 13 return book; 14 } 15 16 checkOutBook(id: number): boolean { 17 const book = this.books.find(b => b.id === id); 18 if (book && !book.isCheckedOut) { 19 book.isCheckedOut = true; 20 return true; 21 } 22 return false; 23 } 24 25 getAvailableBooks(): Book[] { 26 return this.books.filter(b => !b.isCheckedOut); 27 } 28}
L2Private state prevents external tampering
L6Sequential ID generation ensures uniqueness
L15Return boolean for operation success/failure
L22Filter creates new array without mutating original

Key Takeaways

  • •Use private properties to encapsulate state and prevent external modification
  • •Return copies of data rather than direct references to maintain control over state
  • •Design methods with single responsibilities and meaningful return values for better usability
Loading...