Ojasa Mirai

Ojasa Mirai

ReactJS

Loading...

Learning Level

🟒 BeginnerπŸ”΅ Advanced
πŸ“‹ Rendering Lists with map()πŸ”‘ Keys and Reconciliation✨ Unique Keys⚠️ Common Key MistakesπŸ” Filtering Lists↕️ Sorting and Reorderingβž• Dynamic Lists
Reactjs/Lists Keys/Dynamic Lists

βž• Dynamic Lists

Understanding Dynamic Lists

πŸ”„ A dynamic list is one that changes during runtimeβ€”items are added, removed, or updated based on user actions or data changes. This is where proper key management becomes critical.

With dynamic lists, the order and content change constantly, making unique stable keys essential for maintaining correct component state.


Adding Items to a List

Adding to the End

interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

function TodoApp() {
  const [todos, setTodos] = React.useState<Todo[]>([
    { id: 1, text: "Learn React", completed: false },
    { id: 2, text: "Build a project", completed: false }
  ]);
  const [input, setInput] = React.useState("");

  const addTodo = () => {
    if (input.trim()) {
      setTodos([
        ...todos,
        {
          id: Date.now(),  // βœ… Unique ID for new item
          text: input,
          completed: false
        }
      ]);
      setInput("");
    }
  };

  return (
    <div>
      <input
        value={input}
        onChange={(e) => setInput(e.target.value)}
        onKeyPress={(e) => e.key === "Enter" && addTodo()}
        placeholder="Add a new todo..."
      />
      <button onClick={addTodo}>Add</button>
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            <input type="checkbox" checked={todo.completed} />
            {todo.text}
          </li>
        ))}
      </ul>
    </div>
  );
}

Adding to the Beginning

function NotificationList() {
  const [notifications, setNotifications] = React.useState<Notification[]>([]);

  const addNotification = (message: string) => {
    const newNotification: Notification = {
      id: Date.now(),
      message,
      timestamp: new Date()
    };

    // Add to the beginning
    setNotifications([newNotification, ...notifications]);
  };

  return (
    <div>
      <button onClick={() => addNotification("New notification!")}>
        Add Notification
      </button>
      <ul>
        {notifications.map(notif => (
          <li key={notif.id}>
            {notif.message} at {notif.timestamp.toLocaleTimeString()}
          </li>
        ))}
      </ul>
    </div>
  );
}

interface Notification {
  id: number;
  message: string;
  timestamp: Date;
}

Removing Items

Remove by ID

interface Item {
  id: number;
  name: string;
}

function ItemList() {
  const [items, setItems] = React.useState<Item[]>([
    { id: 1, name: "Item 1" },
    { id: 2, name: "Item 2" },
    { id: 3, name: "Item 3" }
  ]);

  const removeItem = (id: number) => {
    setItems(items.filter(item => item.id !== id));
  };

  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>
          {item.name}
          <button onClick={() => removeItem(item.id)}>Delete</button>
        </li>
      ))}
    </ul>
  );
}

Remove by Index

function ShoppingList() {
  const [items, setItems] = React.useState<string[]>(["Milk", "Bread", "Eggs"]);

  const removeItem = (index: number) => {
    setItems(items.filter((_, i) => i !== index));
  };

  return (
    <ul>
      {items.map((item, index) => (
        <li key={`${item}-${index}`}>
          {item}
          <button onClick={() => removeItem(index)}>Remove</button>
        </li>
      ))}
    </ul>
  );
}

Updating Items

interface Post {
  id: number;
  title: string;
  likes: number;
}

function PostList() {
  const [posts, setPosts] = React.useState<Post[]>([
    { id: 1, title: "React Tips", likes: 10 },
    { id: 2, title: "TypeScript Guide", likes: 5 }
  ]);

  const likePost = (id: number) => {
    setPosts(posts.map(post =>
      post.id === id ? { ...post, likes: post.likes + 1 } : post
    ));
  };

  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>
          <h3>{post.title}</h3>
          <p>Likes: {post.likes}</p>
          <button onClick={() => likePost(post.id)}>πŸ‘ Like</button>
        </li>
      ))}
    </ul>
  );
}

Complex Todo List Example

interface Todo {
  id: number;
  text: string;
  completed: boolean;
  createdAt: Date;
}

function ComplexTodoApp() {
  const [todos, setTodos] = React.useState<Todo[]>([]);
  const [input, setInput] = React.useState("");

  const addTodo = () => {
    if (input.trim()) {
      setTodos([
        ...todos,
        {
          id: Date.now(),
          text: input,
          completed: false,
          createdAt: new Date()
        }
      ]);
      setInput("");
    }
  };

  const toggleTodo = (id: number) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  const deleteTodo = (id: number) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  const completedCount = todos.filter(t => t.completed).length;
  const totalCount = todos.length;

  return (
    <div style={{ maxWidth: "500px", margin: "20px auto" }}>
      <h2>My Todos</h2>
      <p>Completed: {completedCount} of {totalCount}</p>

      <div style={{ marginBottom: "20px" }}>
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyPress={(e) => e.key === "Enter" && addTodo()}
          placeholder="Add a new todo..."
          style={{ padding: "8px", width: "70%" }}
        />
        <button onClick={addTodo} style={{ marginLeft: "10px" }}>
          Add
        </button>
      </div>

      <ul style={{ listStyle: "none", padding: 0 }}>
        {todos.map(todo => (
          <li
            key={todo.id}
            style={{
              padding: "10px",
              border: "1px solid #ddd",
              marginBottom: "10px",
              borderRadius: "4px",
              display: "flex",
              alignItems: "center",
              gap: "10px"
            }}
          >
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id)}
            />
            <span
              style={{
                flex: 1,
                textDecoration: todo.completed ? "line-through" : "none",
                color: todo.completed ? "#999" : "black"
              }}
            >
              {todo.text}
            </span>
            <button onClick={() => deleteTodo(todo.id)}>Delete</button>
          </li>
        ))}
      </ul>

      {todos.length === 0 && <p style={{ color: "#999" }}>No todos yet!</p>}
    </div>
  );
}

<details><summary>πŸ“š More Examples</summary>

Insert Item at Specific Position

interface Card {
  id: number;
  title: string;
}

function CardList() {
  const [cards, setCards] = React.useState<Card[]>([
    { id: 1, title: "Card 1" },
    { id: 2, title: "Card 2" },
    { id: 3, title: "Card 3" }
  ]);

  const insertCard = (title: string, position: number) => {
    const newCard: Card = { id: Date.now(), title };
    const newCards = [...cards];
    newCards.splice(position, 0, newCard);
    setCards(newCards);
  };

  return (
    <div>
      <button onClick={() => insertCard("New Card", 1)}>
        Insert at Position 1
      </button>
      <ul>
        {cards.map(card => (
          <li key={card.id}>{card.title}</li>
        ))}
      </ul>
    </div>
  );
}

Batch Updates

function BatchUpdateExample() {
  const [items, setItems] = React.useState([
    { id: 1, name: "Item 1", selected: false },
    { id: 2, name: "Item 2", selected: false },
    { id: 3, name: "Item 3", selected: false }
  ]);

  const selectAll = () => {
    setItems(items.map(item => ({ ...item, selected: true })));
  };

  const deselectAll = () => {
    setItems(items.map(item => ({ ...item, selected: false })));
  };

  return (
    <div>
      <button onClick={selectAll}>Select All</button>
      <button onClick={deselectAll}>Deselect All</button>
      <ul>
        {items.map(item => (
          <li key={item.id} style={{
            backgroundColor: item.selected ? "#e3f2fd" : "white"
          }}>
            {item.name}
          </li>
        ))}
      </ul>
    </div>
  );
}

</details>


Summary Table

OperationMethodKey Consideration
Add to end`[...items, newItem]`ID must be unique
Add to start`[newItem, ...items]`Use stable IDs, not index
Remove by ID`.filter(item => item.id !== id)`Stable keys unaffected
Update item`.map(item => item.id === id ? {...item, prop} : item)`Keep ID same
Batch update`.map(item => {...item, prop})`All IDs stable
Insert at position`.splice(index, 0, item)`Create new array copy first

βœ… Key Takeaways

1. βœ… Always use unique, stable IDs when adding dynamic items

2. βœ… Create a new array when adding/removingβ€”don't mutate directly

3. βœ… Use `.filter()` to remove items by ID

4. βœ… Use `.map()` to update items while keeping others unchanged

5. βœ… `Date.now()` works for generating unique IDs in simple apps

6. βœ… Use `UUID` library for production apps to avoid ID collisions

7. βœ… Batch operations with `.map()` are efficient

8. βœ… Always create new array references for React to detect changes

9. βœ… Dynamic lists benefit most from proper key management

10. βœ… Test list operations with reordering, filtering, and batch changes


πŸŽ“ Next Steps

You've mastered the basics of lists and keys! Now explore advanced patterns and optimizations.

β†’ Go to Advanced Content

Challenge: Build a fully functional todo app


Resources

Python Docs

Ojasa Mirai

Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.

Learn Deep β€’ Build Real β€’ Verify Skills β€’ Launch Forward

Courses

PythonFastapiReactJSCloud

Β© 2026 Ojasa Mirai. All rights reserved.

TwitterGitHubLinkedIn