Lists with State
Lists with State: CRUD Operations
The most common real-world requirement is managing a list through state adding, editing, and removing items dynamically. The golden rule: never mutate state arrays directly. Always return new arrays from your state updater functions.
C :Create : Add an item
Use the spread operator: setItems(prev => [...prev, newItem])
R: Read : Display items
Use .map() to render the state array with a key on each item.
U: Update :Edit an item
Use .map() to return a new array, replacing only the matching item.
D: Delete : Remove an item
Use .filter() to return a new array excluding the deleted item.
Full CRUD Todo / Course Manager
JSX
import { useState } from 'react'; function CourseManager() { const [courses, setCourses] = useState([ { id: 1, title: 'React Basics', published: true }, { id: 2, title: 'SEO Mastery', published: false }, ]); const [newTitle, setNewTitle] = useState(''); const [nextId, setNextId] = useState(3); // ── CREATE ────────────────────────────────────────── const addCourse = () => { if (!newTitle.trim()) return; setCourses((prev) => [ ...prev, { id: nextId, title: newTitle.trim(), published: false } ]); setNextId((n) => n + 1); setNewTitle(''); }; // ── UPDATE — toggle published ────────────────────── const togglePublish = (id) => { setCourses((prev) => prev.map((c) => c.id === id ? { ...c, published: !c.published } : c ) ); }; // ── DELETE ──────────────────────────────────────── const removeCourse = (id) => { setCourses((prev) => prev.filter((c) => c.id !== id)); }; return ( <div> <h2>Course Manager</h2> {/* Add new course */} <div> <input value={newTitle} onChange={(e) => setNewTitle(e.target.value)} placeholder="New course title..." onKeyDown={(e) => e.key === 'Enter' && addCourse()} /> <button onClick={addCourse}>Add Course</button> </div> {/* READ — render the list */} <ul> {courses.map((course) => ( <li key={course.id}> <span>{course.title}</span> <span>{course.published ? '✅ Published' : '📝 Draft'}</span> {/* UPDATE */} <button onClick={() => togglePublish(course.id)}> {course.published ? 'Unpublish' : 'Publish'} </button> {/* DELETE */} <button onClick={() => removeCourse(course.id)}> Delete </button> </li> ))} </ul> <p>Total: {courses.length} courses</p> </div> ); }
