React İle Web Uygulamaları İçin Dinamik Bir Yazdırılabilir Fatura Sistemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Projeye başlamadan önce bilgisayarınızda Node.js (v18 veya üzeri) yüklü olmalıdır. React projemizi oluştururken modern bir derleyici olan Vite kullanacağız. Ayrıca, yazdırma işlemlerinde bileşenleri izole etmek ve yazdırma stilini yönetmek için react-to-print kütüphanesini kullanacağız. Bu kütüphane, yazdırma sırasında CSS stillerinin korunmasını ve sadece belirli bir bileşenin yazdırılmasını sağlar.

Projenizi başlatmak için terminalinizde şu komutları çalıştırın:

npx create-vite@latest fatura-sistemi --template react
cd fatura-sistemi
npm install
npm install react-to-print

Kurulum tamamlandıktan sonra, projenin dizin yapısını düzenleyerek components/Invoice.jsx adında bir dosya oluşturun. Bu dosya, faturamızın görsel şablonunu barındıracaktır.

Adım 1: Fatura Veri Yapısını ve Bileşenini Oluşturma

Dinamik bir fatura sistemi için verinin doğru formatlanması gerekir. Fatura bileşenimiz, kendisine props (özellikler) olarak gelen veriyi render etmelidir. Bu, faturanın her seferinde farklı kullanıcılar ve tutarlar için güncellenebilmesini sağlar.

Aşağıdaki kod, faturanın temel yapısını oluşturan Invoice bileşenidir:

import React from 'react';

const Invoice = React.forwardRef(({ data }, ref) => {
  return (
    

Adım 2: Yazdırma İşlevini Tetikleme

Yazdırma işlemini tetiklemek için bir buton ve useReactToPrint hook'unu kullanacağız. Bu hook, yazdırma penceresini açmadan önce CSS stillerini enjekte etmemize ve yazdırma öncesi/sonrası işlemler yapmamıza olanak tanır.

import { useRef } from 'react';
import { useReactToPrint } from 'react-to-print';
import Invoice from './components/Invoice';

function App() {
  const componentRef = useRef();
  const handlePrint = useReactToPrint({
    content: () => componentRef.current,
    documentTitle: 'Fatura-123',
  });

  const invoiceData = {
    customerName: 'Ahmet Yılmaz',
    items: [{ name: 'React Eğitimi', price: 500 }, { name: 'Hosting', price: 100 }],
    total: 600
  };

  return (
    
Faturayı Yazdır
); }

Burada useRef kullanarak faturanın referansını alıyoruz ve bunu handlePrint fonksiyonu ile yazdırma motoruna gönderiyoruz.

Adım 3: Yazdırma İçin CSS Optimizasyonu

Ekranda gördüğümüz tasarım ile kağıt üzerinde çıkan tasarım genellikle farklıdır. Yazdırma sırasında sayfa kenar boşluklarını ve arka plan renklerini düzenlemek için @media print sorgularını kullanmalıyız. react-to-print bu stilleri yazdırma sırasında otomatik olarak uygular.

/* index.css */
@media print {
  body {
    -webkit-print-color-adjust: exact;
  }
  .no-print {
    display: none;
  }
  @page {
    margin: 20mm;
  }
}

Bu CSS kuralları, faturanın kağıda sığmasını sağlar ve yazdırma butonunu kağıtta çıkmasını engellemek için no-print sınıfını kullanmanıza yardımcı olur.

Adım 4: Dinamik Veri Yönetimi ve Güvenlik

Fatura verileri genellikle bir API üzerinden gelir. Kullanıcıdan alınan verilerin veya veritabanından çekilen bilgilerin XSS (Siteler Arası Betik Çalıştırma) saldırılarına karşı korunması için verileri render ederken doğrudan HTML olarak değil, React'in güvenli veri bağlama yöntemleriyle ekrana basmalısınız.

Aşağıdaki tablo, yazdırma yöntemlerinin karşılaştırmasını sunar:

Yöntem Avantajı Dezavantajı
Tarayıcı `window.print()` Ek kütüphane gerektirmez. Stil yönetimi çok zordur.
`react-to-print` Bileşen bazlı kontrol sağlar. Ek bağımlılık ekler.
PDF Oluşturma (jsPDF) Dosya olarak kaydetme imkanı. CSS düzeni sıfırdan kurulmalıdır.
Kritik Güvenlik Uyarısı: Kullanıcı tarafından girilen verileri faturaya yansıtırken asla dangerouslySetInnerHTML kullanmayın. Eğer HTML içeriği render etmeniz gerekiyorsa, dompurify gibi kütüphanelerle veriyi temizlediğinizden emin olun. Aksi takdirde, kötü niyetli kullanıcılar fatura içeriğine script enjekte edebilir.

Adım 5: Gelişmiş Özellikler - Sayfa Sonu Yönetimi

Faturanız uzunsa, sayfaların doğru yerden bölünmesi gerekir. CSS'deki page-break-after özelliği, uzun listelerde sayfa düzenini korumak için hayat kurtarıcıdır.

.page-break {
  page-break-after: always;
}

Bu sınıfı, faturanızın belirli bölümlerine (örneğin her 20 satırdan sonra) ekleyerek, yazıcının sayfayı nerede böleceğini belirleyebilirsiniz.

Sıkça Sorulan Sorular

Yazdırılan faturada logolar neden görünmüyor?

Tarayıcılar varsayılan olarak "Arka plan grafiklerini yazdır" seçeneğini kapalı tutabilir. CSS'de -webkit-print-color-adjust: exact; kullanarak tarayıcıyı görselleri ve renkleri basmaya zorlayabilirsiniz.

Faturayı PDF olarak nasıl kaydederim?

Kullanıcı "Yazdır" butonuna bastığında açılan sistem penceresinde "PDF olarak kaydet" seçeneğini seçebilir. Yazılım tarafında bunu zorunlu kılmak için jsPDF ve html2canvas kütüphanelerini entegre etmeniz gerekir.

Fatura numarası gibi değişkenleri nasıl güncel tutarım?

React'in useState veya useContext yapısını kullanarak fatura verilerini merkezi bir state'te tutun. Veri değiştiğinde Invoice bileşeni otomatik olarak güncellenecektir.

Yazdırma penceresi açılmadan önce veri yüklemesini nasıl beklerim?

react-to-print'in onBeforeGetContent özelliğini kullanarak, yazdırma başlamadan önce verinin hazır olup olmadığını kontrol eden bir loading (yükleme) durumu yönetebilirsiniz.

Mobil cihazlarda yazdırma özelliği çalışır mı?

Evet, ancak mobil tarayıcıların yazdırma yetenekleri masaüstüne göre daha kısıtlıdır. Web uygulamanızda "PDF İndir" seçeneği sunmak, mobil kullanıcılar için daha iyi bir alternatiftir.

Performans Optimizasyonu ve Büyük Ölçekli Veri Yönetimi

Fatura sisteminizde yüzlerce kalemden oluşan faturalar veya karmaşık tablo yapıları varsa, React bileşenlerinin yeniden render edilmesi (re-render) performans sorunlarına yol açabilir. Özellikle yazdırma işlemi sırasında tüm DOM ağacının taranması, tarayıcıyı geçici olarak dondurabilir. Bu durumu engellemek için React.memo ve useMemo kancalarını stratejik olarak kullanmalısınız.

Ayrıca, büyük veri setlerini işlerken "Lazy Loading" yaklaşımını benimsemek, yazdırma anında sadece gerekli olan veri bloklarının belleğe yüklenmesini sağlar. Aşağıdaki örnekte, fatura kalemlerinin performanslı bir şekilde nasıl render edileceğini görebilirsiniz:

import React, { useMemo } from 'react';

const InvoiceItems = React.memo(({ items }) => {
  const totalAmount = useMemo(() => {
    return items.reduce((acc, item) => acc + item.price * item.quantity, 0);
  }, [items]);

  return (
    
        {items.map((item) => (
          
        ))}
      
{item.name} {item.quantity} {item.price} TL
); });

Yazdırma Süreçlerinde Hata Ayıklama Teknikleri

Yazdırma sırasında karşılaşılan en yaygın sorunlar; CSS stillerinin eksik yüklenmesi, görsellerin kaybolması veya sayfa sonu (page-break) hesaplamalarındaki hatalardır. Bu sorunları gidermek için tarayıcı geliştirici araçlarını (DevTools) "Print Simulation" modunda kullanmak kritik öneme sahiptir.

Geliştirici Araçlarında Yazdırma Modunu Etkinleştirme

  • Chrome veya Edge tarayıcısında F12 tuşuna basarak geliştirici araçlarını açın.
  • Ctrl + Shift + P (Mac için Cmd + Shift + P) tuşlarına basın.
  • Açılan komut satırına "Rendering" yazın ve Show Rendering seçeneğini seçin.
  • Alt panelde çıkan Emulate CSS media type seçeneğini "print" olarak değiştirin.

Bu yöntem, yazdırma penceresini tetiklemeden doğrudan tarayıcı üzerinde faturanızın kağıt üzerindeki görünümünü anlık olarak düzenlemenize olanak tanır. Eğer stilleriniz bu modda düzgün görünüyorsa, yazdırma penceresinde de sorunsuz çalışacaktır.

Hata Ayıklama İçin Kontrol Listesi

  1. CSS @media print: Tüm stillerinizin @media print bloğu içinde tanımlandığından emin olun.
  2. Asset Yolları: Logo ve ikonlarınızın mutlak (absolute) URL ile çağrıldığını doğrulayın.
  3. Z-Index Sorunları: Yazdırma sırasında katmanların üst üste binip binmediğini kontrol edin.
  4. Console Logları: Yazdırma tetiklendiğinde bileşenin veriyi alıp almadığını useEffect içerisinde kontrol edin.
useEffect(() => {
  if (isPrinting) {
    console.log("Fatura yazdırma moduna geçti. Veri durumu:", invoiceData);
  }
}, [isPrinting, invoiceData]);

Sonuç

React ile dinamik bir fatura sistemi oluşturmak, doğru kütüphaneler ve CSS teknikleri kullanıldığında oldukça verimli bir süreçtir. Bu rehberde, bileşen tabanlı yaklaşımla verinin nasıl yönetileceğini, react-to-print ile yazdırma işlemlerinin nasıl optimize edileceğini ve güvenlik önlemlerinin nasıl alınacağını öğrendiniz. Bir sonraki adım olarak, sisteminize jspdf kütüphanesini entegre ederek kullanıcılarınıza faturayı doğrudan PDF dosyası olarak indirme seçeneği sunabilirsiniz.

Sorumluluk Reddi: Bu rehberde paylaşılan kodlar eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce, veritabanı bağlantılarınızın güvenliğini, girdi temizleme (sanitization) süreçlerini ve sunucu tarafı yetkilendirme kontrollerini mutlaka gözden geçirin.
Bu yazıya tepkinizi paylaşın:
Mert Çelik

Hobi ve teknik beceriler üzerine eğitici içerikler kurguluyorum. Okuyucuların günlük hayatta karşılaştığı sorunlara uygulanabilir çözümler sunmayı hedefliyorum.

Yorumlar (0)

Yorum Yaz