Waktunya ngoding proyek React pertamamu! Aplikasikan semua konsep seperti komponen, props, state, event handling, dan list rendering untuk membangun aplikasi To-Do List interaktif dari awal.
17m bacaanKuis WajibMicro Badge Lesson
Bikin Karya Nyata: Bangun Aplikasi To-Do List Keren Pake React!
Teori udah, konsep udah, sekarang saatnya PRAKTIK! Cara terbaik buat bener-bener ngeresapin semua yang udah kita pelajari soal ReactJS adalah dengan langsung ngebangun sesuatu. Di bagian ini, kita bakal ngebikin Aplikasi To-Do List sederhana tapi fungsional pake React.
Fitur yang Mau Kita Bikin:
Nampilin daftar tugas.
Form buat nambahin tugas baru.
Kemampuan buat nandain tugas sebagai "selesai" (misal, teksnya dicoret).
Kemampuan buat ngehapus tugas.
Ini bakal ngelibatin hampir semua konsep inti React yang udah kita bahas: komponen, JSX, props, state (useState), event handling, conditional rendering, dan list rendering (pake .map() dan key).
Siapin VS Code-mu, pastiin proyek Vite + React-mu udah siap (atau bikin baru kalau mau!), dan yuk kita mulai ngoding!
Langkah 0: Struktur Awal Proyek
Anggap kamu udah punya proyek React yang dibuat pake Vite (misalnya, npm create vite@latest my-todo-app -- --template react). Kita bakal banyak kerja di folder src/.
Kita bisa mulai dengan ngebersihin file src/App.jsx dan src/App.css dari konten default Vite.
Langkah 1: Komponen Utama Aplikasi (App.jsx)
Komponen App ini bakal jadi "otak" utama yang nyimpen daftar tugas (state) dan ngatur logika dasarnya.
Disini kita bakal ngebuat state todos yang bakal nyimpen daftar tugas di local storage (Simak ulang cara nyimpen data di Browser (localStorage)
). Kita juga bakal ngebuat fungsi-fungsi handler seperti addTodo, toggleComplete, dan deleteTodo untuk ngubah state tersebut.
File src/App.jsx:
jsx
import React, { useState, useEffect } from 'react';import './App.css'; // Kita akan isi style-nya nantiimport TodoForm from './components/TodoForm'; // Komponen buat form inputimport TodoList from './components/TodoList'; // Komponen buat nampilin daftar tugasfunction App() { // State buat nyimpen semua tugas. Nilai awalnya array kosong. // Tiap tugas bakal jadi objek: { id: ..., text: ..., isCompleted: ... } const [todos, setTodos] = useState(() => { // Coba ambil todos dari localStorage pas pertama kali load const savedTodos = localStorage.getItem('todos'); return savedTodos ? JSON.parse(savedTodos) : []; }); // useEffect buat nyimpen todos ke localStorage setiap kali 'todos' berubah useEffect(() => { localStorage.setItem('todos', JSON.stringify(todos)); }, [todos]); // Fungsi buat nambahin tugas baru const addTodo = (text) => { if (!text.trim()) return; // Jangan tambah kalau teks kosong atau cuma spasi const newTodo = { id: Date.now(), // ID unik sederhana pake timestamp text: text, isCompleted: false, }; setTodos([...todos, newTodo]); // Tambah todo baru ke array todos yang lama }; // Fungsi buat toggle status selesai/belum tugas const toggleComplete = (id) => { setTodos( todos.map(todo => todo.id === id ? { ...todo, isCompleted: !todo.isCompleted } : todo ) ); }; // Fungsi buat ngehapus tugas const deleteTodo = (id) => { setTodos(todos.filter(todo => todo.id !== id)); }; return ( <div className="app-container"> <header> <h1>To-Do List React Saya!</h1> </header> <main> <TodoForm onAddTodo={addTodo} /> {/* Kirim fungsi addTodo sebagai prop */} <TodoList todos={todos} onToggleComplete={toggleComplete} onDeleteTodo={deleteTodo} /> {/* Kirim daftar todos & fungsi-fungsi sebagai props */} </main> <footer> <p>Total Tugas: {todos.length} | Selesai: {todos.filter(t => t.isCompleted).length}</p> </footer> </div> );}export default App;
Bedah App.jsx:
State todos: Pake useState([]) buat nyimpen array of objek tugas. Kita juga nambahin logika buat ngambil data dari localStorage pas pertama kali load dan nyimpennya lagi setiap kali todos berubah pake useEffect. Ini biar daftar tugasnya gak ilang pas halaman di-refresh!
addTodo(text): Fungsi buat nambahin objek tugas baru ke state todos. Perhatiin cara pake spread operator (...todos) buat bikin array baru tanpa ngemutasi state lama.
toggleComplete(id): Fungsi buat ngubah status isCompleted dari tugas tertentu. Dia nge-map array todos, nyari tugas yang ID-nya cocok, terus nge-return objek tugas baru dengan status isCompleted yang dibalik.
deleteTodo(id): Fungsi buat ngehapus tugas. Dia nge-filter array todos buat ngembaliin semua tugas yang ID-nya GAK SAMA dengan ID yang mau dihapus.
Return JSX: Ngerender komponen TodoForm dan TodoList (yang bakal kita bikin), sambil ngirim state todos dan fungsi-fungsi handler itu sebagai props. Footer juga nampilin info jumlah tugas.
Langkah 2: Komponen Form Input (TodoForm.jsx)
Komponen ini tugasnya nampilin input field dan tombol buat nambahin tugas baru.
Buat folder baru src/components/ terus bikin file TodoForm.jsx di dalemnya.
File src/components/TodoForm.jsx:
jsx
import React, { useState } from 'react';function TodoForm({ onAddTodo }) { // Nerima prop onAddTodo dari App const [inputText, setInputText] = useState(''); const handleSubmit = (event) => { event.preventDefault(); // Cegah reload if (!inputText.trim()) return; // Validasi input kosong onAddTodo(inputText); // Panggil fungsi dari App buat nambah todo setInputText(''); // Kosongin input field lagi }; return ( <form onSubmit={handleSubmit} className="todo-form"> <input type="text" value={inputText} onChange={(e) => setInputText(e.target.value)} placeholder="Ketik tugas baru..." className="todo-input" /> <button type="submit" className="todo-button">Tambah</button> </form> );}export default TodoForm;
Bedah TodoForm.jsx:
Dia punya state lokal inputText buat ngontrol nilai input field.
Pas form di-submit, dia manggil fungsi onAddTodo (yang sebenernya adalah addTodo dari App.jsx) sambil ngasih teks inputnya. Ini contoh lifting state up via fungsi callback!
Langkah 3: Komponen Daftar Tugas (TodoList.jsx) dan Item Tugas (TodoItem.jsx)
TodoList bakal ngerender semua tugas. Tiap tugasnya bakal dirender sama komponen TodoItem.
Nerima satu objek todo dan dua fungsi handler (onToggleComplete, onDeleteTodo) sebagai props.
Nampilin teks tugas.
Style-nya (dicoret atau enggak) tergantung todo.isCompleted (conditional styling).
Punya tombol "Selesai/Batal" yang manggil onToggleComplete dengan todo.id.
Punya tombol "Hapus" yang manggil onDeleteTodo dengan todo.id.
(Styling di sini pake inline style objek biar simpel buat contoh, tapi di proyek beneran mending pake CSS Modules atau Tailwind).
File src/components/TodoList.jsx:
jsx
import React from 'react';import TodoItem from './TodoItem';function TodoList({ todos, onToggleComplete, onDeleteTodo }) { if (todos.length === 0) { return <p className="empty-message">Belum ada tugas nih, santai dulu!</p>; } return ( <ul className="todo-list"> {todos.map(todo => ( <TodoItem key={todo.id} // Key wajib buat list! todo={todo} onToggleComplete={onToggleComplete} onDeleteTodo={onDeleteTodo} /> ))} </ul> );}export default TodoList;
Bedah TodoList.jsx:
Nerima array todos dan dua fungsi handler dari App.jsx.
Kalau todos-nya kosong, dia nampilin pesan.
Kalau ada tugas, dia nge-map array todos jadi sekumpulan komponen <TodoItem />, sambil ngoper data todo dan fungsi handler-nya sebagai props ke tiap TodoItem. Jangan lupa key={todo.id}!
Langkah 4: Styling Global (src/App.css dan src/index.css)
Kita kasih sedikit style biar gak terlalu polos.
File src/index.css (biasanya buat reset atau style global banget):
Pastikan kamu ada di folder root proyekmu di terminal.
Jalanin npm run dev (kalau belum jalan).
Buka browser ke alamat http://localhost:5173/ (atau port yang dikasih Vite).
Harusnya kamu udah liat aplikasi To-Do List sederhanamu! Coba tambahin tugas, tandain selesai, hapus tugas. Liat juga localStorage di DevTools browser (Tab Application > Local Storage) buat liat data tugasmu kesimpen di sana.
Proyek mini ini ngasih kamu gambaran gimana caranya:
Mecah UI jadi komponen-komponen (App, TodoForm, TodoList, TodoItem).
Ngelola state aplikasi (todos di App, inputText di TodoForm).
Ngoper data dan fungsi antar komponen pake props.
Nanganin event pengguna (submit form, klik tombol).
Ngerender list data pake .map() dan pentingnya key.
Nerapin conditional styling (buat tugas yang selesai).
Nambahin sedikit persistensi data pake localStorage dan useEffect.
Ini adalah fondasi yang kuat banget! Dari sini, kamu bisa coba kembangin lagi fiturnya, misalnya:
Edit tugas yang udah ada.
Filter tugas (semua, aktif, selesai).
Ngasih prioritas ke tugas.
Dan banyak lagi!
Selamat udah berhasil ngebikin aplikasi React pertamamu yang beneran fungsional! Ini bukti kalau kamu udah mulai "ngeh" sama cara kerja React. Teruslah berlatih dan bikin proyek-proyek lain!
Checkpoint KuisTarget: 70%
Kuis Proyek Mini ReactJS (To-Do List)
Kuis ini wajib untuk sertifikat. Kamu tetap bisa lanjut ke pelajaran berikutnya dan mengerjakannya nanti.