React'te Event Handling: Olay Yönetimi Rehberi

React'te Event Handling: Olay Yönetimi Rehberi
Event handling (olay yönetimi), kullanıcı etkileşimlerini yakalamak ve yanıt vermek için her web uygulamasının temel taşıdır. React'te event handling, native DOM event'lerinden farklı bir mekanizma kullanır: Synthetic Events (Sentetik Olaylar). Bu rehberde React'te event handling'in nasıl çalıştığını, yaygın olay türlerini ve ileri seviye teknikleri detaylı olarak ele alacağız.
Synthetic Events (Sentetik Olaylar)
React, tarayıcılar arası tutarlılık sağlamak için native DOM event'lerini sarmalayan bir SyntheticEvent sistemi kullanır. Bu sistem, tüm tarayıcılarda aynı API'yi sunar:
function EventDemo() {
const handleClick = (event) => {
// event bir SyntheticEvent'tir
console.log('Event tipi:', event.type); // 'click'
console.log('Hedef eleman:', event.target); // tıklanan element
console.log('Geçerli hedef:', event.currentTarget); // handler'ın bağlı olduğu element
console.log('Zaman damgası:', event.timeStamp);
// Native event'e erişim (nadiren gerekli)
console.log('Native event:', event.nativeEvent);
};
return <button onClick={handleClick}>Tıkla</button>;
}
React event handler'ları HTML attribute'larından farklı olarak camelCase yazılır:onclickyerineonClick,onchangeyerineonChange. Handler olarak string değil, fonksiyon referansı verilir.
Yaygın Event Türleri
Mouse Events
function MouseEvents() {
return (
<div
onClick={(e) => console.log('Tıklandı', e.clientX, e.clientY)}
onDoubleClick={() => console.log('Çift tıklandı')}
onMouseEnter={() => console.log('Mouse girdi')}
onMouseLeave={() => console.log('Mouse çıktı')}
onContextMenu={(e) => {
e.preventDefault(); // Sağ tık menüsünü engelle
console.log('Sağ tıklama');
}}
style={{ padding: '40px', backgroundColor: '#f0f0f0' }}
>
Mouse event alanı
</div>
);
}
Form Events
function FormEvents() {
const [formData, setFormData] = useState({
username: '',
email: '',
bio: '',
role: 'user'
});
// Tüm input'lar için tek handler
const handleChange = (e) => {
const { name, value, type, checked } = e.target;
setFormData(prev => ({
...prev,
[name]: type === 'checkbox' ? checked : value
}));
};
const handleSubmit = (e) => {
e.preventDefault(); // Sayfa yenilenmesini engelle
console.log('Form verileri:', formData);
};
return (
<form onSubmit={handleSubmit}>
<input
name="username"
value={formData.username}
onChange={handleChange}
onFocus={() => console.log('Input odaklandı')}
onBlur={() => console.log('Input odağı kaybetti')}
placeholder="Kullanıcı adı"
/>
<input
name="email"
type="email"
value={formData.email}
onChange={handleChange}
placeholder="E-posta"
/>
<textarea
name="bio"
value={formData.bio}
onChange={handleChange}
placeholder="Biyografi"
/>
<select name="role" value={formData.role} onChange={handleChange}>
<option value="user">Kullanıcı</option>
<option value="admin">Yönetici</option>
<option value="editor">Editör</option>
</select>
<button type="submit">Kaydet</button>
</form>
);
}
Keyboard Events
function KeyboardShortcuts() {
const [output, setOutput] = useState('');
const handleKeyDown = (e) => {
// Ctrl+Enter ile gönder
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
console.log('Ctrl+Enter: Gönder');
return;
}
// Escape ile temizle
if (e.key === 'Escape') {
setOutput('');
return;
}
// Ctrl+B ile kalın yazı toggle
if (e.key === 'b' && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
console.log('Ctrl+B: Kalın yazı');
}
};
return (
<div>
<textarea
value={output}
onChange={(e) => setOutput(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Ctrl+Enter: Gönder | Esc: Temizle"
rows={5}
/>
<p>Karakter sayısı: {output.length}</p>
</div>
);
}
İpucu: onKeyDown ve onKeyUp arasında önemli bir fark vardır. onKeyDown tuşa basıldığında (karakter ekranda görünmeden önce), onKeyUp tuş bırakıldığında tetiklenir. Form validasyonu ve kısayollar için genellikle onKeyDown tercih edilir.
Event Delegation ve Propagation
function EventPropagation() {
const handleParentClick = () => {
console.log('Parent tıklandı');
};
const handleChildClick = (e) => {
// Olayın üst elemanlara yayılmasını durdur
e.stopPropagation();
console.log('Child tıklandı');
};
return (
<div onClick={handleParentClick} style={{ padding: '20px', backgroundColor: '#eee' }}>
<p>Parent alan - tıklayın</p>
<button onClick={handleChildClick}>
Child buton (stopPropagation)
</button>
</div>
);
}
// Event delegation pattern - liste için tek handler
function TaskList({ tasks, onToggle, onDelete }) {
const handleClick = (e) => {
const { action, taskId } = e.target.dataset;
if (!action) return;
const id = Number(taskId);
if (action === 'toggle') onToggle(id);
if (action === 'delete') onDelete(id);
};
return (
<ul onClick={handleClick}>
{tasks.map(task => (
<li key={task.id}>
<span data-action="toggle" data-task-id={task.id}>
{task.done ? '✓' : '○'} {task.text}
</span>
<button data-action="delete" data-task-id={task.id}>Sil</button>
</li>
))}
</ul>
);
}
Drag and Drop Events
function DragDropList() {
const [items, setItems] = useState(['React', 'Vue', 'Angular', 'Svelte']);
const [draggedIndex, setDraggedIndex] = useState(null);
const handleDragStart = (e, index) => {
setDraggedIndex(index);
e.dataTransfer.effectAllowed = 'move';
};
const handleDragOver = (e, index) => {
e.preventDefault();
if (draggedIndex === index) return;
setItems(prev => {
const updated = [...prev];
const [removed] = updated.splice(draggedIndex, 1);
updated.splice(index, 0, removed);
return updated;
});
setDraggedIndex(index);
};
const handleDragEnd = () => {
setDraggedIndex(null);
};
return (
<ul className="drag-list">
{items.map((item, index) => (
<li
key={item}
draggable
onDragStart={(e) => handleDragStart(e, index)}
onDragOver={(e) => handleDragOver(e, index)}
onDragEnd={handleDragEnd}
style={{
opacity: draggedIndex === index ? 0.5 : 1,
cursor: 'grab',
padding: '8px',
margin: '4px 0',
backgroundColor: '#f5f5f5',
borderRadius: '4px'
}}
>
{item}
</li>
))}
</ul>
);
}
Uyarı: Event handler'larda doğrudan setState yerine inline arrow function kullanımı (onClick={() => handleClick(id)}) her render'da yeni bir fonksiyon oluşturur. Bu, React.memo ile sarılmış bileşenlerde gereksiz re-render'lara yol açabilir. Performans kritik durumlarda useCallback kullanın.
Sonuç
React'te event handling, Synthetic Events sistemi sayesinde tarayıcılar arası tutarlı ve güvenli bir deneyim sunar. Form yönetimi, klavye kısayolları, drag-and-drop ve event delegation gibi pattern'leri doğru kullanarak etkileşimli ve performanslı uygulamalar oluşturabilirsiniz. preventDefault ve stopPropagation'ı bilinçli kullanın, gereksiz re-render'ları önlemek için handler fonksiyonlarınızı optimize edin.