Çalışan bir görev panosuyla React öğrenin: bileşenler, JSX, props, useState, kontrollü formlar, sabit anahtarlar ve değişmez güncellemeler; tam App.jsx örneği ve uygulamalı kontroller.
React öğrenirken her kavramı ekranda görülebilen bir davranışla eşleştirmek işinizi kolaylaştırır. Bu rehberde küçük bir görev panosu oluşturacağız: yeni görev yazacak, listeye ekleyecek, tamamlanma durumunu değiştirecek ve görevleri filtreleyeceğiz. Böylece bileşen, props, olay ve state kavramlarını aynı uygulamada kullanacağız. Sonunda elinizde çalıştırabileceğiniz tek dosyalık bir örnek, verinin arayüzde nasıl ilerlediğine ilişkin bir açıklama ve hataları araştırmak için uygulayabileceğiniz bir kontrol sırası olacak.
React öncesinde hangi bilgiler gerekli?
HTML ile başlık, liste, düğme ve form oluşturabilmelisiniz. Bir etiketi giriş alanına bağlamayı ve CSS ile temel boşlukları düzenlemeyi bilmeniz de yararlı olur. JavaScript tarafında fonksiyonlar, nesneler, diziler, modül içe aktarma ve parçalayarak atama üzerinde çalışın. Özellikle map ve filter yöntemlerini küçük örneklerle deneyin. Bir diziden yeni bir dizi üretebilmeniz ve bir fonksiyonu başka bir fonksiyona parametre olarak aktarabilmeniz yeterli bir başlangıçtır.
React, değişen verilerle bu verileri gösteren arayüz arasındaki ilişkiyi yönetmenizi sağlar. HTML anlamını veya CSS yerleşimini ortadan kaldırmaz. Tarayıcı, sunucu ve veritabanının birlikte nasıl çalıştığını görmek için modern web geliştirme rehberine göz atabilirsiniz. Buradaki alıştırma yalnızca tarayıcıda çalışır; kullanıcı hesabı, uzak API veya veritabanı içermez. Bu sınır, ilk aşamada veri akışını takip etmeyi kolaylaştırır.
Vite ile öğrenme projesini hazırlayın
React belgeleri yeni uygulamalar için bir framework ile başlamayı önerir; öğrenmek veya özel gereksinimler için sıfırdan kurulum yolunu da açıklar. Bu alıştırmada temel kavramlara odaklanmak için Vite kullanıyoruz. Gerçek bir ürünün araç seçimi; sayfa yönlendirmesi, veri yükleme, barındırma ve görüntüleme ihtiyaçlarını kapsamalıdır. Ayrıntılar React proje önerilerinde ve sıfırdan uygulama oluşturma rehberinde bulunur.
Vite’ın güncel gereksinimlerini karşılayan, desteklenen bir Node.js LTS sürümü kurun. Terminali alıştırma projelerinizi sakladığınız klasörde açın. Aşağıdaki komutları sırayla çalıştırın. Kurulum aracı bağımlılıkları hemen kurup sunucuyu başlatmayı teklif ederse bu isteğe bağlı adımı reddedin ve aşağıdaki açık komutlarla devam edin.
node --version
npm create vite@latest react-task-board -- --template react
cd react-task-board
npm install
npm run dev
Geliştirme sunucusunun yazdırdığı yerel adresi tarayıcıda açın. Düzenleme yaparken terminal açık kalsın; işiniz bittiğinde Ctrl+C ile durdurabilirsiniz. react şablonu JavaScript ve JSX kullanır. Editörde src/App.jsx dosyasını açın. Birazdan içeriğini örnekle tamamen değiştireceksiniz; oluşturulan src/main.jsx dosyası yerinde kalacak. Ek paket veya stil dosyası gerekmez. Başlangıç şablonunun stilleri görünümü etkileyebilir.
Bileşen, JSX ve props ilişkisi
Panoyu App adlı bir üst bileşen, her görev satırını ise TaskItem adlı bir alt bileşen olarak düşünün. Bileşen adları büyük harfle başlar. JSX, bileşenin döndürdüğü görünümü tanımlar; süslü parantezler içinde JavaScript ifadeleri kullanılır. Etiketleri kapatın, CSS sınıfları için className yazın ve yan yana dönen öğeleri bir üst öğede veya Fragment içinde gruplayın. Sözdizimi resmî JSX rehberinde açıklanır.
Görev satırı üç props alır: görev nesnesi ve iki geri çağırma fonksiyonu. Satır görevi gösterir; değişiklik gerektiğinde bu fonksiyonlarla üst bileşene haber verir. Böylece koleksiyonun sahibi ile bir satırın görünümünden sorumlu bölüm ayrılır. Props salt okunur girdilerdir; props aktarma belgesini inceleyebilirsiniz. TaskItem tanımını App dışında tutuyoruz; panodaki her güncelleme yeni bir bileşen türü oluşturmamalıdır.
Çalışan App.jsx dosyasının tamamı
Aşağıdaki bloğun tamamını src/App.jsx içine kopyalayıp kaydedin. Başlangıçta iki görev vardır ve biri tamamlanmıştır. Böylece üç filtreyi de hemen deneyebilirsiniz. Arayüz Türkçedir; değişken adları ise kod boyunca aynı kavramı takip edebilmeniz için İngilizce bırakılmıştır. Görev kimlikleri, görünüm değişse de aynı kalır.
import { useState } from "react";
const initialTasks = [
{ id: "read-components", text: "Bileşenler hakkında bir bölüm oku", done: false },
{ id: "try-board", text: "Görev panosunu dene", done: true },
];
function TaskItem({ task, onToggle, onRemove }) {
return (
<li>
<label>
<input
type="checkbox"
checked={task.done}
onChange={() => onToggle(task.id)}
/>
{" "}
{task.done ? <s>{task.text}</s> : task.text}
</label>
{" "}
<button
type="button"
onClick={() => onRemove(task.id)}
aria-label={"Sil: " + task.text}
>
Sil
</button>
</li>
);
}
export default function App() {
const [tasks, setTasks] = useState(initialTasks);
const [draft, setDraft] = useState("");
const [filter, setFilter] = useState("all");
const [error, setError] = useState("");
const completedCount = tasks.filter((task) => task.done).length;
const visibleTasks = tasks.filter((task) =>
filter === "all" ? true : filter === "done" ? task.done : !task.done
);
function handleAdd(event) {
event.preventDefault();
const text = draft.trim();
if (!text) {
setError("Eklemeden önce bir görev adı yazın.");
return;
}
const newTask = { id: crypto.randomUUID(), text, done: false };
setTasks((currentTasks) => [...currentTasks, newTask]);
setDraft("");
setError("");
}
function toggleTask(id) {
setTasks((currentTasks) =>
currentTasks.map((task) =>
task.id === id ? { ...task, done: !task.done } : task
)
);
}
function removeTask(id) {
setTasks((currentTasks) =>
currentTasks.filter((task) => task.id !== id)
);
}
return (
<main lang="tr" dir="ltr" style={{ maxWidth: "40rem", padding: "1.5rem", textAlign: "start" }}>
<h1>Küçük görev panom</h1>
<p>Toplam görev: {tasks.length} — Tamamlanan: {completedCount}</p>
<form onSubmit={handleAdd}>
<label htmlFor="new-task">Yeni görev</label>
{" "}
<input
id="new-task"
value={draft}
maxLength={120}
onChange={(event) => {
setDraft(event.target.value);
setError("");
}}
aria-invalid={error ? true : undefined}
aria-describedby={error ? "task-error" : undefined}
/>
{" "}
<button type="submit">Görev ekle</button>
{error ? <p id="task-error" role="alert">{error}</p> : null}
</form>
<p>
<label htmlFor="task-filter">Görevleri göster</label>
{" "}
<select
id="task-filter"
value={filter}
onChange={(event) => setFilter(event.target.value)}
>
<option value="all">Tümü</option>
<option value="open">Bekleyenler</option>
<option value="done">Tamamlananlar</option>
</select>
</p>
{visibleTasks.length > 0 ? (
<ul>
{visibleTasks.map((task) => (
<TaskItem
key={task.id}
task={task}
onToggle={toggleTask}
onRemove={removeTask}
/>
))}
</ul>
) : (
<p>Bu görünümde görev bulunmuyor.</p>
)}
<p>Görevler yalnızca bu sayfa oturumunda tutulur.</p>
</main>
);
}
Bir kullanıcı işlemini baştan sona izleyin
Alana “İletişim formunu incele” yazın. Değişiklik işleyicisi alanın güncel değerini okur ve setDraft çağırır. React yeni değerle yeniden görüntü oluşturur; kontrollü alan da bu değeri gösterir. Form gönderildiğinde handleAdd çalışır. preventDefault, tarayıcının normal form gönderimiyle sayfadan ayrılmasını engeller. Metnin kenarlarındaki boşluklar temizlenir, boş sonuç reddedilir, ardından yeni görev oluşturulup listeye eklenir.
Son adımda giriş alanı ve hata mesajı temizlenir. Düğmeye tıklamanın yanında Enter ile göndermeyi de deneyin. İşlemi yalnızca düğmenin tıklama olayına bağlasaydık, formun doğal kullanımını gereksiz yere zorlaştırmış olurduk. Burada form gönderimi işlemin tek giriş noktasıdır; kullanıcı hangi yöntemle gönderirse göndersin aynı doğrulama ve ekleme sırası çalışır.
useState, mevcut değeri ve onu güncelleyen fonksiyonu döndürür. Güncelleyiciyi çağırmak sonraki görüntülemeyi planlar; çalışmakta olan olay işleyicisindeki değişkeni anında değiştirmez. Hook çağrılarını bileşenin üst düzeyinde, koşullu dönüşlerden önce yapın. Kurallar useState referansında bulunur. Örnekte yalnızca görevler, yazı taslağı, seçili filtre ve doğrulama mesajı saklanır; bunlar ayrı ayrı değişebilen bilgilerdir.
Dizileri eski veriyi değiştirmeden güncelleyin
Ekleme sırasında yayma sözdizimiyle yeni bir dizi kurulur. Silme sırasında filter, seçilen kimlik dışındaki görevleri içeren bir dizi üretir. Tamamlanma durumunu değiştiren map ise eşleşen görev için yeni bir nesne oluşturur; diğer nesneler kullanılmaya devam eder. tasks.push(...) veya doğrudan task.done ataması kullanmayın. Bu yaklaşım React dizi güncelleme rehberinde anlatılır.
Görev güncellemeleri setTasks((currentTasks) => ...) biçimindedir; yeni değer önceki koleksiyondan hesaplanır. Fonksiyon, güncelleme kuyruğundaki en son değeri alır. Bu hesaplama saf kalmalıdır. Yeni kimliği bu yüzden güncelleyicinin içinde değil, olay işleyicisinde oluşturuyoruz. Geliştirme kontrolleri güncelleyiciyi birden fazla kez çağırabilir; içine ağ isteği veya dış veriyi değiştiren işlem koymayın. Taslak ya da filtre tamamen yeni bir değere atanırken doğrudan değer geçilebilir.
Üç görevden ortadakini sildiğinizi düşünün. Sonuçta iki görev kalır, ancak kimlikleri değişmez. Aynı düşünceyi daha sonra görev adını düzenlemek için de kullanabilirsiniz: doğru kimliği bulun, o nesnenin değiştirilmiş bir kopyasını döndürün ve diğer görevleri koruyun. Bu küçük dönüşümleri anlayabilmek, daha fazla düğme eklemekten önce sağlamlaştırılması gereken temel beceridir.
Kalıcı anahtarlar ve anlaşılır boş durumlar
Her satırda key={task.id} kullanılır. Kimlik görevin kendisini tanımlar; dizi indeksi ise filtreleme veya silmeyle değişebilen konumu tanımlar. Görüntüleme sırasında rastgele anahtar üretmek de her güncellemede kimliği değiştirir. Liste oluşturma belgesi, anahtarların neden sabit kalması gerektiğini açıklar. İki görev aynı metne sahip olsa bile ayrı kimliklerle bağımsız kalır.
Örnek, sonuç varsa listeyi, yoksa açıklayıcı bir mesajı gösterir. Tamamlanan görevleri silip “Tamamlananlar” filtresini seçin. Listenin boşalması, bütün görevlerin silindiği anlamına gelmez. Üstteki toplam tüm koleksiyonu sayar; filtre yalnızca görünen alt kümeyi değiştirir. length > 0 kontrolü, yanlışlıkla ekrana sıfır yazdırmadan bu kararı açıkça ifade eder.
Kontrollü form ve Effect gerektirmeyen hesaplamalar
Metin alanında hem value hem onChange bulunur. Değişiklik işleyicisini kaldırırsanız normal yazma davranışı durur. Taslağın boş metinle başlaması, alanın baştan sona kontrollü kalmasını sağlar. Görünür etiket ve alana bağlanan hata mesajı kullanımını açıklar. Sözleşme React input referansında anlatılır. Onay kutusu boolean değerini checked üzerinden alır.
Tamamlanan görev sayısı ve görünür liste mevcut state üzerinden hesaplanır. Bunları ayrıca saklamak, her ekleme, silme ve tamamlamada eşitleme gerektirirdi. Bu hesaplamalar için Effect kullanılmaz; ayrım Effect gerektirmeyen durumlar rehberinde açıklanır. Küçük bir listede doğrudan filtreleme yeterlidir. Önbellekleme veya ayrı state kütüphanesi eklemeden önce ölçülebilen bir sorununuz olsun.
Yeni özelliklerden önce davranışı doğrulayın
- Normal bir görev ekleyin, ardından yalnızca boşluk gönderin. İlk işlem görev eklemeli, ikinci işlem hata göstermelidir.
- Aynı ada sahip iki görev oluşturun ve yalnızca birini tamamlayın. İkisinin bağımsız kaldığını doğrulayın.
- Üç filtre arasında geçiş yapın. Filtreli görünümde görev silin veya tamamlayın; sayaçları kontrol edin.
- Tab, Enter ve Space kullanarak alanları, düğmeleri, seçim listesini ve onay kutularını çalıştırın.
- Sayfayı yenileyin. Veriler yalnızca bellekte tutulduğu için başlangıç görevleri geri gelmelidir.
Daha sonra üretim çıktısının hazırlanabildiğini kontrol edin ve yerel önizlemeyi açın:
npm run build
npm run preview
Başarılı derleme, kodun derlenebildiğini gösterir; bütün etkileşimlerin doğru olduğunu kanıtlamaz. Önizleme adresinde aynı davranış kontrollerini tekrar uygulayın. Her işlemden önce beklediğiniz sonucu yazmak, bir hata olduğunda hangi veri geçişini araştıracağınızı belirlemenize yardımcı olur.
Sık görülen hatalar ve sonraki adım
- Boş ekran: tarayıcı konsolundaki ilk hatayı ve terminal mesajını okuyun; JSX kapanışlarını, içe aktarma adlarını ve varsayılan dışa aktarmayı kontrol edin.
- Durmayan yeniden görüntüleme: görüntüleme sırasında güncelleyici çağırmayın; olaya
onClick={() => onRemove(task.id)}gibi bir fonksiyon verin. - Yazılamayan giriş alanı: değişiklik işleyicisini ve state değerini kontrol edin. DOM değerini elle değiştirmek kontrollü değerle çakışır.
crypto.randomUUIDkullanılamıyor: modern bir tarayıcıda yerel geliştirme adresini veya HTTPS kullanın; örnek bu ortamlar içindir.- Yeni görev görünmüyor: “Tamamlananlar” filtresi yeni, tamamlanmamış görevleri gizler. Eklemenin başarısız olduğunu düşünmeden önce “Tümü” seçeneğine dönün.
Sıradaki alıştırmanız görev adı düzenleme veya kalan görev sayacı olabilir. Ardından bu davranışlar için etkileşim testleri yazın; kalıcı saklama, sunucu doğrulaması ve yükleme ile hata durumlarına geçin. Çok dilli yerleşimler için Arapça ve RTL site tasarımı rehberini, proje büyüdüğünde mobil site hızını iyileştirme rehberini kullanabilirsiniz. Çalışma bir iş uygulamasına dönüşürse gerekli sayfa ve süreçleri yazılı hale getirip geliştirme hizmetlerimizi değerlendirebilirsiniz.