Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce bilgisayarınızda Node.js'in güncel bir sürümünün yüklü olduğundan emin olmalısınız. React uygulaması oluşturmak için Vite gibi modern araçları kullanmanızı öneriyoruz. Geliştirme ortamınızı hazırlamak için aşağıdaki adımları takip edin.
- Node.js: En az 18.x veya daha yeni bir sürüm.
- Paket Yöneticisi: npm, yarn veya pnpm.
- React Sürümü: 18.x veya 19.x (Hooks desteği için).
Terminalinizi açın ve boş bir React projesi başlatmak için şu komutları çalıştırın:
npm create vite@latest geri-sayim-uygulamasi -- --template react
cd geri-sayim-uygulamasi
npm install
npm run dev
Bu komutlar, projenizin temel iskeletini oluşturacak ve yerel bir sunucuda çalışmasını sağlayacaktır. Artık kodlamaya başlamaya hazırsınız.
Adım Adım Geri Sayım Mantığını Kurma
Geri sayım sayacının temel mantığı, hedef tarih ile şimdiki zaman arasındaki farkı sürekli hesaplamaktır. React'te bu işlemi useEffect ve setInterval kullanarak gerçekleştiririz. İlk olarak, zaman farkını saniye, dakika, saat ve gün birimlerine ayıran bir yapı kuralım.
const hesaplaZamanFarki = (hedefTarih) => {
const fark = +new Date(hedefTarih) - +new Date();
let zaman = {};
if (fark > 0) {
zaman = {
gun: Math.floor(fark / (1000 * 60 * 60 * 24)),
saat: Math.floor((fark / (1000 * 60 * 60)) % 24),
dakika: Math.floor((fark / 1000 / 60) % 60),
saniye: Math.floor((fark / 1000) % 60),
};
}
return zaman;
};
Bu fonksiyon, hedef tarih ile şu anki zaman arasındaki farkı milisaniye cinsinden hesaplar ve bir nesne olarak döner. Negatif değerleri engellemek için if (fark > 0) kontrolünü ekledik.
useEffect ile Zamanlayıcıyı Yönetme
React bileşenlerinde zamanlayıcı kullanırken en büyük hata, bellek sızıntılarına (memory leaks) neden olan interval'leri temizlememektir. useEffect kancası içerisinde setInterval kullanarak her saniye güncellenen bir yapı kuracağız.
import { useState, useEffect } from 'react';
const GeriSayim = ({ hedefTarih }) => {
const [zaman, setZaman] = useState(hesaplaZamanFarki(hedefTarih));
useEffect(() => {
const timer = setInterval(() => {
setZaman(hesaplaZamanFarki(hedefTarih));
}, 1000);
return () => clearInterval(timer);
}, [hedefTarih]);
return (
{zaman.gun}g {zaman.saat}s {zaman.dakika}d {zaman.saniye}s
);
};
Burada return () => clearInterval(timer) satırı hayati önem taşır. Bileşen ekrandan kaldırıldığında (unmount), interval'in arka planda çalışmaya devam etmesini engeller.
Geri Sayım Bileşenini Özelleştirme ve Stil Verme
Sayaç sadece rakamlardan ibaret olmamalıdır. Kullanıcıya görsel olarak zengin bir deneyim sunmak için CSS modüllerini veya popüler bir kütüphane olan Tailwind CSS'i kullanabilirsiniz. Aşağıda basit bir CSS yapısı ile bileşeni nasıl şekillendireceğinizi görebilirsiniz.
/* Countdown.css */
.timer-container {
display: flex;
gap: 1rem;
font-family: sans-serif;
}
.time-box {
background: #333;
color: #fff;
padding: 10px;
border-radius: 5px;
}
Bu stil dosyası, sayaç değerlerinin kutucuklar içinde daha düzenli görünmesini sağlar. Bileşeninizde bu sınıfları className özelliği ile uygulayarak tasarımı tamamlayabilirsiniz.
Performans ve Hata Denetimi
Dinamik sayaçlarda en sık karşılaşılan sorunlardan biri, "zaman sapması" veya bileşenin gereksiz yere tekrar render edilmesidir. useMemo kullanarak hesaplama fonksiyonunu optimize edebilir ve sadece hedef tarih değiştiğinde hesaplama yapılmasını sağlayabilirsiniz.
Güvenlik Uyarısı: Kullanıcıdan alınan hedef tarihleri doğrudan DOM'a yazarken XSS (Cross-Site Scripting) saldırılarına karşı dikkatli olun. Eğer tarih bir API'den geliyorsa, veriyi her zaman doğruluğunu kontrol ederek (sanitize) işleyin.
Aşağıdaki tablo, farklı geri sayım yöntemlerini karşılaştırmaktadır:
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| setInterval | Basit ve hızlı | Zaman sapması olabilir |
| requestAnimationFrame | Çok akıcı | Karmaşık yapı |
| Sunucu Zamanı Senkronizasyonu | En doğru sonuç | API maliyeti |
Sıkça Sorulan Sorular
Geri sayım bittiğinde ne yapmalıyım?
zaman nesnesinin tüm değerleri 0 olduğunda veya fark değişkeni 0'ın altına düştüğünde, bir onFinish callback fonksiyonu tetikleyerek kullanıcıya bir mesaj gösterebilir veya bir yönlendirme yapabilirsiniz.
Sayfa yenilendiğinde sayaç sıfırlanır mı?
Evet, sayaç sadece tarayıcı belleğinde tutulur. Eğer sayacın kaldığı yerden devam etmesini istiyorsanız, hedef tarihi localStorage veya bir veritabanında tutarak bileşen yüklendiğinde oradan okumalısınız.
Neden saniyeler bazen atlıyor?
JavaScript'in tek iş parçacıklı (single-threaded) yapısı nedeniyle, yoğun işlemler sırasında setInterval gecikebilir. Çok hassas sayaçlar için Date.now() farkını sürekli kontrol eden bir yapı kullanmak daha sağlıklıdır.
Birden fazla sayaç kullanabilir miyim?
Kesinlikle. Bileşeninizi hedefTarih prop'u alacak şekilde tasarladığınız için, aynı sayfada farklı tarihlere sahip istediğiniz kadar sayaç oluşturabilirsiniz.
Mobil cihazlarda pil ömrünü etkiler mi?
Sürekli çalışan bir interval, mobil cihazlarda pil tüketimini artırabilir. Eğer sayaç ekranın görünür alanında değilse, IntersectionObserver API kullanarak sayacın sadece kullanıcı ekrandayken çalışmasını sağlayabilirsiniz.
Geri Sayım Sayacını Bir Event Sistemi ile Entegre Etme
Sayaç sıfırlandığında sadece bir metin göstermek yerine, uygulamanızın diğer bölümlerini tetikleyen bir Event (Olay) Sistemi kurmak, kullanıcı deneyimini bir üst seviyeye taşır. Örneğin, bir satış kampanyası bittiğinde "Satın Al" butonunu devre dışı bırakabilir veya kullanıcıyı otomatik olarak başka bir sayfaya yönlendirebilirsiniz.
Callback Fonksiyonları ile Kontrol
Bileşeninize bir onComplete prop'u ekleyerek, ebeveyn bileşenin sayaç bittiğinde ne yapacağına karar vermesini sağlayabilirsiniz.
const Countdown = ({ targetDate, onComplete }) => {
const [timeLeft, setTimeLeft] = useState(calculateTimeLeft(targetDate));
useEffect(() => {
const timer = setInterval(() => {
const newTime = calculateTimeLeft(targetDate);
setTimeLeft(newTime);
if (newTime.total clearInterval(timer);
}, [targetDate, onComplete]);
return {timeLeft.seconds}s;
};
Alternatif Yaklaşım: Kütüphane Kullanımı
Eğer projeniz çok karmaşık zaman dilimleri (timezone), yerelleştirme (i18n) veya hassas milisaniye takibi gerektiriyorsa, tekerleği yeniden icat etmek yerine kanıtlanmış kütüphaneleri tercih etmek daha güvenli olabilir. react-countdown paketi, bu tür ihtiyaçlar için endüstri standardı kabul edilir.
Neden Hazır Kütüphane Seçilmeli?
- Zaman Dilimi Desteği: Sunucu saati ile istemci saati arasındaki farkları otomatik yönetir.
- SSR Uyumluluğu: Next.js gibi sunucu taraflı render alan framework'lerde "hydration" hatalarını önlemek için optimize edilmiştir.
- Gelişmiş Formatlama: Gün, saat, dakika ve saniye ayrıştırmasını kendi içinde yapar.
import Countdown from 'react-countdown';
const App = () => (
(
{hours}:{minutes}:{seconds}
)}
/>
);
Üretim Ortamı İçin İleri İpuçları ve Test
Sayaçlarınızı yayına almadan önce mutlaka şu iki senaryoyu test etmelisiniz:
- Sistem Saati Değişimi: Kullanıcı cihazının saatini manuel olarak geriye alırsa sayaç nasıl tepki veriyor? (Sunucu tabanlı bir zaman damgası kullanmak bu sorunu çözer).
- Sekme Uyku Modu: Tarayıcılar, arka plandaki sekmelerde
setIntervalhızını düşürebilir. Bu durum sayacın "donmuş" gibi görünmesine neden olur.
İpucu: Sekme uyku modundan kaynaklanan sapmaları engellemek için, her saniye yerine Date.now() değerini hedef tarihle karşılaştıran bir "fark hesaplama" mantığı kullanın. Böylece sayaç her tetiklendiğinde güncel zamanı yeniden hesaplayarak senkronizasyonu korumuş olursunuz.
Sonuç
React ile dinamik bir geri sayım sayacı oluşturmak, bileşen yaşam döngüsü ve zaman yönetimi konusunda size önemli yetkinlikler kazandırır. Bu rehberde öğrendiğiniz useEffect temizleme mantığı ve zaman farkı hesaplama teknikleri, sadece sayaçlarda değil, birçok farklı gerçek zamanlı uygulama senaryosunda da işinize yarayacaktır.
Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce hata ayıklama (debugging) süreçlerini tamamlamalı ve güvenlik standartlarına uygun olduğundan emin olmalısınız. Yazılım süreçlerindeki hatalardan kaynaklanabilecek veri kayıpları veya performans sorunları için geliştirici sorumludur.
Bir sonraki adım olarak, bu sayacı bir veritabanı ile entegre ederek kullanıcıya özel etkinlikler oluşturmayı veya sayaç bittiğinde tetiklenen bir "event" sistemi kurmayı deneyebilirsiniz. Başarılar dileriz.

Yorumlar (0)
Yorum Yaz