React İle Sürükle Bırak Özellikli Bir Liste Bileşeni Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Projeye başlamadan önce bilgisayarınızda Node.js'in güncel bir sürümünün (LTS) yüklü olduğundan emin olmalısınız. React projenizi Vite kullanarak hızlıca başlatabilir ve gerekli bağımlılıkları yükleyebilirsiniz. Bu örnekte, sürükle bırak işlemlerini yönetmek için @dnd-kit/core, @dnd-kit/sortable ve @dnd-kit/utilities paketlerini kullanacağız.

npx create-vite@latest surukle-birak-projesi --template react
cd surukle-birak-projesi
npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities

Yukarıdaki komutlar, projenizi kuracak ve sürükle bırak işlemleri için gerekli olan modern kütüphaneleri çalışma ortamınıza dahil edecektir. Bu paketler, dokunmatik ekran desteği ve klavye navigasyonu gibi erişilebilirlik özelliklerini de beraberinde getirir.

Sürükle Bırak Mantığı ve Bileşen Yapısı

Sürükle bırak mantığı, React'te "kontrollü bileşen" prensibiyle çalışır. Liste veriniz bir state (durum) içerisinde tutulur ve kullanıcı bir öğeyi taşıdığında, bu state güncellenerek bileşenin yeniden render edilmesi sağlanır. Aşağıdaki kod bloğunda, temel liste verimizi tanımlıyoruz.

import { useState } from 'react';

const [items, setItems] = useState([
  { id: '1', title: 'Görev 1' },
  { id: '2', title: 'Görev 2' },
  { id: '3', title: 'Görev 3' },
]);

Burada items dizisi, sürükleme işlemi sırasında yer değiştirecek olan verilerimizi temsil eder. Her öğenin benzersiz bir id değerine sahip olması, dnd-kit kütüphanesinin öğeleri doğru şekilde tanımlayabilmesi için zorunludur.

Sıralanabilir Liste Bileşenini Oluşturma

Sıralanabilir bir liste oluşturmak için @dnd-kit/sortable kütüphanesinden gelen useSortable hook'unu kullanırız. Bu hook, bir bileşeni sürüklenebilir ve bırakılabilir hale getiren gerekli özellikleri (attributes) ve referansları (listeners) sağlar.

import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

export function SortableItem({ id, title }) {
  const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    padding: '10px',
    border: '1px solid #ccc',
    marginBottom: '5px',
    backgroundColor: 'white'
  };

  return (
    
{title}
); }

Bu bileşen, sürükleme sırasında oluşan transform değerini CSS'e dönüştürerek akıcı bir animasyon sağlar. setNodeRef, kütüphanenin DOM üzerindeki konumu takip etmesine yardımcı olur.

Sürükleme İşlemini Yönetme (DndContext)

Tüm listenin sürükleme olaylarını yönetmek için DndContext sarmalayıcısına ihtiyacımız vardır. Bu sarmalayıcı, sürükleme başladığında, sürükleme sırasında ve bırakma gerçekleştiğinde tetiklenen olayları (event) yakalar.

import { DndContext, closestCenter } from '@dnd-kit/core';
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';

function App() {
  return (
    
      
        {items.map(item => )}
      
    
  );
}

collisionDetection parametresi, sürüklenen öğenin bırakıldığı noktayı nasıl hesaplayacağımızı belirler. closestCenter, öğenin merkezine en yakın olan hedefi algılamak için en ideal yöntemdir.

Öğelerin Yer Değiştirme Mantığı

Sürükleme işlemi bittiğinde, handleDragEnd fonksiyonu tetiklenir. Bu fonksiyon, dizideki öğelerin yerini değiştirmekten sorumludur. arrayMove yardımcı fonksiyonu, bu işlemi güvenli bir şekilde gerçekleştirmemizi sağlar.

import { arrayMove } from '@dnd-kit/sortable';

function handleDragEnd(event) {
  const { active, over } = event;

  if (active.id !== over.id) {
    setItems((items) => {
      const oldIndex = items.findIndex((i) => i.id === active.id);
      const newIndex = items.findIndex((i) => i.id === over.id);
      return arrayMove(items, oldIndex, newIndex);
    });
  }
}

Bu kod bloğu, sürüklenen öğenin (active) ve bırakılan yerin (over) id'lerini karşılaştırır. Eğer öğe farklı bir konuma bırakıldıysa, arrayMove ile diziyi güncelleriz.

Yöntemlerin Karşılaştırılması

Yöntem Avantajı Dezavantajı
dnd-kit Modern, erişilebilir, modüler Öğrenme eğrisi mevcut
react-beautiful-dnd Popüler, görsel olarak zengin Bakımı yavaşladı, güncel değil
HTML5 Drag/Drop API Dış kütüphane gerektirmez Erişilebilirlik ve mobil desteği zayıf

Güvenlik Uyarısı: Kullanıcıdan gelen veriyle liste sıralamasını güncellerken, sunucu tarafında her zaman yetkilendirme kontrolü yapın. Sürükle bırak işlemleri istemci tarafında gerçekleşse de, sıralama verisini veritabanına kaydederken XSS (Cross-Site Scripting) saldırılarına karşı verileri sanitize etmeyi unutmayın.

Sıkça Sorulan Sorular

Sürükle bırak sırasında animasyonları nasıl daha akıcı yapabilirim?

@dnd-kit/sortable içerisinde yer alan SortableContext, varsayılan olarak animasyonları destekler. transition özelliğini useSortable hook'undan alıp CSS'e uyguladığınızdan emin olun.

Bu yöntem mobil cihazlarda çalışır mı?

Evet, dnd-kit kütüphanesi dokunmatik ekranlar için yerleşik desteğe sahiptir ve herhangi bir ek yapılandırma gerektirmez.

İç içe geçmiş listeler oluşturabilir miyim?

Evet, ancak bu durumda her liste için ayrı bir DndContext ve SortableContext yapısı kurmanız gerekecektir.

Performans sorunlarını nasıl engellerim?

Bileşenlerinizi React.memo ile sarmalayarak, sadece değişen öğelerin yeniden render edilmesini sağlayabilirsiniz.

Sürükleme sırasında öğenin görselini nasıl özelleştirebilirim?

DragOverlay bileşenini kullanarak, sürüklenen öğenin o anki görüntüsünü tamamen özelleştirebilir ve farklı bir stil verebilirsiniz.

Sıralama Değişikliklerini Veritabanına Kaydetme (Auto-Save)

Kullanıcı bir öğeyi sürükleyip bıraktığında, bu değişikliğin kalıcı olması için yeni sıralamayı bir API uç noktasına göndermeniz gerekir. dnd-kit içerisinde onDragEnd olayını tetikleyerek güncel diziyi sunucuya iletebilirsiniz. İşte bu süreci yönetmek için basit bir örnek:

const handleDragEnd = async (event) => {
  const { active, over } = event;

  if (active.id !== over.id) {
    const oldIndex = items.findIndex((i) => i.id === active.id);
    const newIndex = items.findIndex((i) => i.id === over.id);
    const newItems = arrayMove(items, oldIndex, newIndex);
    
    setItems(newItems);

    // Veritabanı güncelleme işlemi
    try {
      await fetch('/api/update-order', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ items: newItems }),
      });
    } catch (error) {
      console.error("Sıralama kaydedilemedi:", error);
    }
  }
};

Bu yapıda dikkat etmeniz gereken en önemli nokta, ağ gecikmelerini (latency) yönetmektir. Eğer çok sık sürükleme işlemi yapılıyorsa, debounce fonksiyonu kullanarak API isteklerini sınırlandırmanız sunucu yükünü ciddi oranda azaltacaktır.

Sürükle Bırak Bileşenleri İçin Birim Testleri

Karmaşık arayüz bileşenlerinde sürükle bırak fonksiyonlarının doğruluğunu test etmek, uygulamanın kararlılığı için kritiktir. @testing-library/react ve user-event kütüphanelerini kullanarak sürükleme simülasyonu yapabilirsiniz.

Test senaryonuzda, öğenin başlangıç pozisyonunu ve sürükleme sonrası yeni pozisyonunu kontrol etmeniz gerekir. Ancak dnd-kit gibi kütüphaneler DOM tabanlı hesaplamalar yaptığı için, test ortamında getBoundingClientRect gibi metodların mock (taklit) edilmesi gerekebilir.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import SortableList from './SortableList';

test('öğeler sürüklendiğinde sıralama değişmeli', async () => {
  render();
  
  const items = screen.getAllByRole('listitem');
  const firstItem = items[0];
  const secondItem = items[1];

  // Sürükle bırak simülasyonu
  await userEvent.pointer([
    { keys: '[MouseLeft>]', target: firstItem },
    { coords: { x: 0, y: 500 }, target: secondItem },
    { keys: '[/MouseLeft]' }
  ]);

  const updatedItems = screen.getAllByRole('listitem');
  expect(updatedItems[0]).toHaveTextContent('İkinci Öğe');
});

Testlerde Dikkat Edilmesi Gerekenler

  • Koordinat Hesaplama: Test ortamında fiziksel bir ekran olmadığı için getBoundingClientRect değerlerini manuel olarak mock'lamanız gerekebilir.
  • Asenkron İşlemler: dnd-kit animasyonları asenkron çalışır; testlerinizde findBy sorgularını kullanarak DOM'un güncellenmesini bekleyin.
  • Erişilebilirlik: Sürükle bırak listenizin klavye ile yönetilebilir olduğunu tabindex ve aria-describedby özelliklerini test ederek doğrulayın.

Sonuç

React ile sürükle bırak özellikli bir liste bileşeni oluşturmak, doğru kütüphane seçimi ve state yönetimi ile oldukça verimli bir süreçtir. Bu rehberde öğrendiğiniz dnd-kit kullanımı, projenize modern bir kullanıcı deneyimi kazandıracaktır. Bir sonraki adım olarak, sürükleme bittikten sonra yeni sıralamayı bir API aracılığıyla sunucuya kaydeden bir "Auto-Save" (otomatik kaydetme) mekanizması eklemeyi deneyebilirsiniz.

Yazılım geliştirmede güvenlik ve performans, kullanıcı deneyiminin temelidir. Kodunuzu her zaman güncel tutun ve kütüphane dokümantasyonlarını periyodik olarak kontrol ederek en iyi pratikleri uygulamaya devam edin.

Bu yazıya tepkinizi paylaşın:
Burak Çelik

Doğa sporları, kampçılık ve açık hava aktiviteleri konularında uzmanlaşmış bir rehber yazarıyım. Yeni başlayanlar için güvenli ve keyifli bir deneyim sunacak, teknik bilgisi yüksek içerikler üretiyorum.

Yorumlar (18)

18
okuyucu bu yazı hakkında yorum yaptı. Siz de deneyiminizi paylaşarak diğer okuyuculara yardımcı olabilirsiniz.
Melis Yıldız
Melis Yıldız 18 Temmuz 2026

Biraz daha karmaşık, yani iç içe listeler (nested) içinde çalışma şansımız var mı bu yapıyla?

Burak Çelik
Burak Çelik 19 Temmuz 2026

Evet, dnd-kit nested sortable yapıları da destekliyor ancak konfigürasyonu biraz daha derinlemesine incelemek gerekiyor. Bir sonraki yazı konusu olabilir!

Tolga İ.
Tolga İ. 23 Temmuz 2026

Örnekteki styling için tailwind mi kullandın yoksa normal css mi? Kodda pek belli olmuyor da.

Fatih Yılmaz
Fatih Yılmaz 24 Temmuz 2026

Gördüğüm kadarıyla Tailwind kullanmış, sınıflar öyle duruyor.

Ayşegül Şen
Ayşegül Şen 24 Temmuz 2026

Dnd-kit gerçekten çok kapsamlı ama yeni başlayanlar için biraz karmaşık gelebilir, senin rehberin sayesinde olayı çözdüm.

Burak Çelik
Burak Çelik 25 Temmuz 2026

Dediğin gibi başta karmaşık gelebiliyor ama mantığını anlayınca çok hızlı ilerliyorsun. Çok sevindim işine yaramasına!

Oğuzhan Kaya
Oğuzhan Kaya 25 Temmuz 2026

Sürükle bırak mantığını bu kadar sade anlatabilen nadir kaynaklardan biri. Teşekkürler.

Hakan Baş
Hakan Baş 28 Temmuz 2026

Kodda hata alıyorum, kütüphaneyi npm ile kurmama rağmen hata veriyo. Versiyon farkı olabilir mi acaba?

Elif Tekin
Elif Tekin 29 Temmuz 2026

Ben de yaşadım onu, react sürümün güncel mi?

Zeynep Nil
Zeynep Nil 30 Temmuz 2026

Cok temiz bir anlatım olmuş, elinize sağlık. Başka kütüphaneler için de benzer içerikler bekliyoruz.

Burak Er
Burak Er 01 Ağustos 2026

Abi anlatım süper ama mobilde sürükleme yaparken sayfayı da kaydırıyor, onu nasıl çözeriz?

Burak Çelik
Burak Çelik 02 Ağustos 2026

Mobildeki o durum genelde 'touch-action: none' CSS özelliği ile çözülüyor, bir dene istersen.

Deniz Kara
Deniz Kara 02 Ağustos 2026

Hocam kod bloklarındaki sortable context kısmını biraz daha detaylandırabilir misin? Tam mantığını oturtamadım da.

Burak Çelik
Burak Çelik 03 Ağustos 2026

Tabii Deniz, sortable context aslında listenin her bir öğesine benzersiz id'ler atayarak yer değişikliğini takip etmemizi sağlıyor. İstersen detaylı bir doküman linki paylaşabilirim.

Selin A.
Selin A. 03 Ağustos 2026

Ya harika bi anlatım olmuş. Daha önce react-beautiful-dnd kullanıyodum ama artık güncel değil, bu çok iyi geldi.

Mert Vural
Mert Vural 04 Ağustos 2026

Aynen, dnd-kit çok daha performanslı bence.

Caner Yılmaz
Caner Yılmaz 05 Ağustos 2026

Eline sağlık Burak, dnd-kit kütüphanesini projeme dahil etmeyi düşünüyordum, tam zamanında yetişen bir rehber oldu.

Burak Çelik
Burak Çelik 06 Ağustos 2026

Rica ederim Caner, dnd-kit gerçekten çok esnek bir kütüphane, projende başarılar!

Yorum Yaz