React İle Özel Kanca Kullanarak Sayfa İçi Kaydırma Efekti Nasıl Yapılır?

React İle Özel Kanca Kullanarak Sayfa İçi Kaydırma Efekti Nasıl Yapılır?
React İle Özel Kanca Kullanarak Sayfa İçi Kaydırma Efekti Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu projeyi uygulamak için bilgisayarınızda Node.js yüklü olmalı ve bir React projesi oluşturmuş olmalısınız. 2026 itibarıyla Vite kullanmanızı öneriyoruz. Projenizi oluşturmak için terminalinizde şu komutu çalıştırabilirsiniz:

npm create vite@latest scroll-app -- --template react
cd scroll-app
npm install

Bu komutlar, modern bir geliştirme ortamı kurmanızı sağlar. React 19 ve üzeri sürümlerle uyumlu bir yapı üzerinden ilerleyeceğiz. Projenin dizin yapısında src/hooks adında bir klasör oluşturmanız, düzenli bir çalışma için ilk adım olacaktır.

Özel Kanca (Custom Hook) Mantığı Nedir?

Özel kancalar, React'in yerleşik kancalarını (useState, useEffect vb.) kullanarak kendi mantığınızı oluşturmanıza olanak tanır. Sayfa içi kaydırma için bir kanca oluşturmanın temel amacı, kaydırma işlemini tetikleyen fonksiyonu ve hedef referansı tek bir noktadan yönetmektir.

Aşağıdaki kod bloğu, temel bir useScrollTo kancasının iskeletini oluşturur:

import { useRef } from 'react';

export const useScrollTo = () => {
  const elementRef = useRef(null);

  const scrollToElement = () => {
    if (elementRef.current) {
      elementRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  };

  return { elementRef, scrollToElement };
};

Bu kanca, bir ref nesnesi döndürür ve bu nesneyi hedeflediğiniz DOM elemanına bağlamanızı sağlar. scrollIntoView metodu, modern tarayıcıların sunduğu yerel bir API'dir.

Adım Adım Özel Kanca Uygulaması

Şimdi bu kancayı gerçek bir bileşen içinde nasıl kullanacağımızı inceleyelim. İlk olarak, kancamızı daha esnek hale getirelim. Sadece kaydırma yapmakla kalmayıp, kaydırma sonrası bir işlem tetiklemek isteyebiliriz.

import { useRef } from 'react';

export const useSmoothScroll = (offset = 0) => {
  const targetRef = useRef(null);

  const executeScroll = () => {
    if (targetRef.current) {
      const top = targetRef.current.getBoundingClientRect().top + window.scrollY - offset;
      window.scrollTo({ top, behavior: 'smooth' });
    }
  };

  return [targetRef, executeScroll];
};

Bu versiyonda, offset parametresi ekleyerek sabit başlık (header) gibi unsurların kaydırmayı engellemesini önlüyoruz. getBoundingClientRect sayesinde elemanın konumunu tam olarak hesaplıyoruz.

Bileşen İçinde Kullanım Örneği

Oluşturduğumuz kancayı bir "Hakkımızda" bölümünde kullanalım. Aşağıdaki örnek, bir buton tıklandığında ilgili bölüme akıcı bir şekilde nasıl gidileceğini gösterir:

import { useSmoothScroll } from './hooks/useSmoothScroll';

function App() {
  const [aboutRef, scrollToAbout] = useSmoothScroll(80);

  return (
    
Hakkımızda Bölümüne Git

Hakkımızda

Burada şirket bilgilerimiz yer almaktadır.

); }

Burada aboutRef değişkenini hedef bölüme bağladık. Butona tıklandığında scrollToAbout fonksiyonu çalışarak sayfayı ilgili bölüme kaydırır.

Yöntem Karşılaştırması

Yöntem Avantaj Dezavantaj
Anchor (a href) Basit, SEO dostu Özelleştirme zor, kaba geçiş
Özel Kanca Tam kontrol, modüler Ekstra kod yükü
Kütüphane (framer-motion) Gelişmiş animasyon Yüksek paket boyutu

Kritik Uyarılar ve Güvenlik

Dikkat: Sayfa içi kaydırma işlemlerinde ref nesnelerinin null olma ihtimalini her zaman kontrol edin. Ayrıca, çok büyük sayfalar üzerinde sürekli kaydırma tetiklemek performans sorunlarına yol açabilir. Kullanıcı etkileşimlerini kısıtlamadan, gereksiz yeniden render (re-render) işlemlerinden kaçının.

Güvenlik açısından, kullanıcı tarafından sağlanan verileri (örneğin URL parametreleri ile kaydırma) doğrudan DOM'a yansıtırken XSS (Cross-Site Scripting) saldırılarına karşı dikkatli olun. DOM elemanlarına doğrudan erişim sağladığınız için, kullanıcı girdilerini sanitize etmeden ref ile etkileşime sokmayın.

Hata Ayıklama (Debugging) İpuçları

Eğer kaydırma çalışmıyorsa, şu adımları izleyin:

  • ref nesnesinin doğru bileşene atandığından emin olun.
  • CSS tarafında scroll-behavior: smooth özelliğinin çakışıp çakışmadığını kontrol edin.
  • Tarayıcı konsolunda targetRef.current değerinin null olup olmadığını console.log ile kontrol edin.

Sıkça Sorulan Sorular

Özel kanca kullanmak neden a etiketinden daha iyidir?

Özel kancalar, kaydırma mantığını JavaScript ile kontrol etmenize olanak tanır. Bu sayede kaydırma bittiğinde bir fonksiyon çalıştırmak veya kaydırma hızını dinamik olarak değiştirmek gibi karmaşık işlemleri kolayca yapabilirsiniz.

Mobil cihazlarda kaydırma performansı nasıl artırılır?

Mobil cihazlarda scrollIntoView metodu genellikle iyi çalışır. Ancak karmaşık animasyonlar eklemek isterseniz, requestAnimationFrame kullanarak kaydırma işlemini optimize edebilirsiniz.

Birden fazla bölüm için tek kanca yeterli mi?

Evet, oluşturduğumuz useSmoothScroll kancasını her bölüm için ayrı bir örnek (instance) olarak çağırarak kullanabilirsiniz.

Sayfa yüklendiğinde belirli bir bölüme otomatik kaydırma yapabilir miyim?

Evet, useEffect kullanarak bileşen yüklendiğinde (mount) executeScroll fonksiyonunu çağırarak otomatik kaydırma sağlayabilirsiniz.

Bu kanca SSR (Server Side Rendering) ile çalışır mı?

Evet, ancak window nesnesine erişmeye çalıştığınız için kanca içindeki işlemleri useEffect içerisinde veya typeof window !== 'undefined' kontrolü ile yapmalısınız.

İleri Seviye Optimizasyon: Kaydırma Animasyonlarını Özelleştirme

Oluşturduğumuz temel useScrollTo kancası, tarayıcının yerleşik scrollIntoView metodunu kullanır. Ancak, kullanıcı deneyimini bir üst seviyeye taşımak için kaydırma hızını, ivmelenmesini (easing) ve ofset değerlerini manuel olarak kontrol etmek isteyebilirsiniz. Özellikle sabit (fixed) header yapısına sahip sitelerde, kaydırma işleminin header'ın altında kalmaması için bir "offset" değeri eklemek kritik bir gereksinimdir.

Aşağıdaki geliştirilmiş yapı, kaydırma işlemini window.scrollTo kullanarak daha hassas bir şekilde yönetmenizi sağlar:

const useSmoothScroll = (offset = 0) => {
  const scrollToElement = (elementId) => {
    const element = document.getElementById(elementId);
    if (element) {
      const elementPosition = element.getBoundingClientRect().top;
      const offsetPosition = elementPosition + window.pageYOffset - offset;

      window.scrollTo({
        top: offsetPosition,
        behavior: "smooth"
      });
    }
  };
  return scrollToElement;
};

Performans İzleme ve Intersection Observer Entegrasyonu

Sayfa içi kaydırma işlemlerinde performans, özellikle karmaşık DOM yapılarında düşebilir. scroll event'ini sürekli dinlemek yerine, IntersectionObserver API'sini kullanarak bileşenlerin görünürlüğünü takip etmek çok daha verimlidir. Bu yöntem, ana iş parçacığını (main thread) yormadan kaydırma pozisyonlarını yönetmenize olanak tanır.

Aşağıdaki örnek, bir bölümün ekrana girip girmediğini kontrol eden ve buna göre tetiklenen bir yapıyı gösterir:

import { useEffect, useState } from 'react';

const useOnScreen = (ref) => {
  const [isIntersecting, setIntersecting] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      setIntersecting(entry.isIntersecting);
    });

    if (ref.current) {
      observer.observe(ref.current);
    }
    return () => {
      observer.disconnect();
    };
  }, [ref]);

  return isIntersecting;
};

Entegrasyon İpuçları

  • Debounce Kullanımı: Eğer kaydırma sırasında bir event tetikliyorsanız, fonksiyonun çok sık çalışmaması için lodash.debounce gibi kütüphanelerle tetikleyiciyi sınırlandırın.
  • GPU Hızlandırma: Kaydırma animasyonları sırasında will-change: transform CSS özelliğini kullanarak tarayıcının donanım hızlandırmasından faydalanabilirsiniz.
  • Erişilebilirlik (A11y): Kaydırma işlemi tamamlandığında, odaklanılan elemente tabIndex="-1" vererek ve element.focus() metodunu çağırarak klavye kullanıcılarının deneyimini iyileştirmeyi unutmayın.
Not: Sayfa içi kaydırma yaparken URL'deki hash (#) değerini güncellemek, kullanıcının "Geri" butonuna bastığında doğru yere dönmesini sağlar. Bunu yapmak için window.history.pushState(null, null, '#element-id') komutunu kullanabilirsiniz.

Sonuç

React ile özel kanca kullanarak sayfa içi kaydırma yapmak, hem kodunuzun okunabilirliğini artırır hem de projenize profesyonel bir dokunuş katar. Bu rehberde öğrendiğiniz modüler yapı sayesinde, artık kendi kaydırma mantığınızı projenin her yerinde kolayca kullanabilirsiniz. Bir sonraki adım olarak, kaydırma esnasında aktif menü öğesini vurgulayan bir "ScrollSpy" kancası geliştirmeyi deneyebilirsiniz.

Kod güvenliği sorumluluk reddi: Bu rehberde paylaşılan kodlar eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce gerekli testleri yapmalı ve projenizin güvenlik politikalarına uygunluğunu denetlemelisiniz.

Bu yazıya tepkinizi paylaşın:
Deniz Arslan

On yıldır pratik ev çözümleri ve hayat kolaylaştıran teknikler üzerine içerik üretiyorum. Okuyucuların karmaşık süreçleri en basit adımlarla çözmelerine yardımcı oluyorum.

Yorumlar (16)

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

Dili çok akıcı kullanmışsın, yazılımcı diliyle anlatman çok iyi olmuş. Devamını bekliyoruz.

Selin G.
Selin G. 22 Temmuz 2026

Kodu denedim ama sanki render performansında bi sıkıntı var gibi, useEffect hook'unu memoize etmek gerekebilir mi?

Oğuzhan B.
Oğuzhan B. 23 Temmuz 2026

Aynen, bende de render sayısı arttı. useRef kullanarak çözdüm ben.

Ahmet Tekin
Ahmet Tekin 24 Temmuz 2026

Sayfa içinde sabit menü kullanırken bu hook hayat kurtarıyor valla. Elinize sağlık.

Derya Nur
Derya Nur 26 Temmuz 2026

Bunu Typescript ile nasıl yazarız? Hook'un tip tanımlamalarını da eklesen efsane olurdu.

Deniz Arslan
Deniz Arslan 27 Temmuz 2026

Harika fikir! Bir sonraki yazımda Typescript versiyonunu da paylaşacağım.

Kaan Efe
Kaan Efe 27 Temmuz 2026

Guzel yazı olmuş tşkler. offset desteği eklemen çok iyi olmuş, çoğu kişi onu atlıyor.

Ebru Yılmaz
Ebru Yılmaz 29 Temmuz 2026

Kod bloklarını mobil cihazda okumak biraz zor, belki fontu biraz büyütebilirsin. İçerik güzel ama.

Deniz Arslan
Deniz Arslan 30 Temmuz 2026

Haklısın Ebru, geri bildirimin için teşekkürler. Tasarım üzerinde çalışıyorum.

Selim Aksoy
Selim Aksoy 30 Temmuz 2026

Çok açıklayıcı bir yazı olmuş. React kancalarını genelde hep karmaşık anlatıyorlar ama sen gayet sadeleştirmişsin. Teşekkürler.

Mertcan Doğan
Mertcan Doğan 01 Ağustos 2026

Ya ben kodları kopyaladım ama console da hata alıyom, neden olabilir acaba? Bi bakabilir misin?

Deniz Arslan
Deniz Arslan 02 Ağustos 2026

Hata mesajını paylaşırsan yardımcı olabilirim Mertcan.

Zeynep S.
Zeynep S. 03 Ağustos 2026

Harika bir anlatım olmuş. Peki bunu smooth scroll ile nasıl birleştiririz? css ile mi halletmek daha mantıklı?

Burak Çelik
Burak Çelik 04 Ağustos 2026

CSS'teki 'scroll-behavior: smooth' özelliği genelde iş görüyor, bence JS ile kasmaya gerek yok.

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

Eline sağlık Deniz hocam, tam da projede scroll olaylarıyla uğraşırken ilaç gibi geldi. Custom hook olayı olayı çok temiz çözüyor.

Deniz Arslan
Deniz Arslan 06 Ağustos 2026

Beğenmene sevindim Caner! Performans için useCallback kullanmayı unutma.

Yorum Yaz