Yasin Ateş

React’te Reusable Component Yazarken Dikkat Edilmesi Gerekenler ⚛️

React’te Reusable Component Yazarken Dikkat Edilmesi Gerekenler ⚛️

Frontend geliştirirken en büyük hedefimiz sadece çalışan değil, aynı zamanda sürdürülebilir, okunabilir ve ölçeklenebilir bir mimari kurmak. Bu hedefin temel taşı ise reusable component yazmak. Bu makalede klasör yapısından custom hook tasarımına, ESLint standartlarından stil yönetimine ve editor ayarlarına kadar reusable component geliştirmenin tüm inceliklerini ele alacağız

Reusable component, farklı yerlerde tekrar tekrar kullanabildiğimiz, dışarıdan aldığı props ile davranışını değiştirebilen ve kendi sorumluluğu net olan bir bileşendir.

Gerçek bir projede bunu somutlaştıralım. Örneğin bir e-ticaret sitesinde; Ürün kartı, sepet butonu, fiyat etiketi gibi onlarca yerde kullanılacak componentler var. Eğer bunları her seferinde sıfırdan yazarsak:

★ Kod tekrarı artar, proje şişer

★ Bir değişiklik yapmak istediğimizde onlarca dosyayı güncellemek zorunda kalırız

★ UI tutarsızlıkları oluşur, kullanıcı deneyimi bozulur

★ Test yazmak ve maintain etmek kabusa döner

Basit bir örnek üzerinden başlayalım:

// Kötü: Her yerde tekrar yazılan button
<button className="blue-btn" onClick={handleClick}>Satın Al</button>
<button className="blue-btn" onClick={handleAdd}>Ekle</button>
// İyi: Tek bir reusable Button component
type ButtonProps = {
 variant?: "primary" | "secondary";
 onClick?: () => void;
 children: React.ReactNode;
};

export function Button({ variant = "primary", onClick, children }: ButtonProps) {
 const baseStyles = "px-4 py-2 rounded font-medium transition";
 const variantStyles =
 variant === "primary"
 ? "bg-blue-600"
 : "bg-gray-200";

 return (
 <button className={`${baseStyles} ${variantStyles}`} onClick={onClick}>
 {children}
 </button>
 );
}

Bu örnekte variant ile görsel davranışı kontrol ediyoruz, children ile içeriği esnek bırakıyoruz, onClick ile dış dünyaya aksiyon veriyoruz. Component sadece render işini yapıyor. İş mantığı yok, API çağrısı yok, global state manipülasyonu yok. Netlik reusable yapının temelidir.

🧠 Single Responsibility: Bir Component Bir İş Yapsın

SOLID presiplerinin başındaki o meşhur “S” 😁

Bir component’in sadece bir şeyi yapması gerekir. Bu konu genelde göz ardı edilir.

Diyelim ki bir UserCard component yazıyoruz. Eğer bu component API çağrısı yapıyor, loading state yönetiyor, error state yönetiyor ve UI render ediyorsa sorumluluklar karışmış demektir.

// hooks/useUser.ts
import { useEffect, useState } from "react";

export function useUser(userId: string) {
 const [user, setUser] = useState<User | null>(null);
 const [isLoading, setIsLoading] = useState(false);

 const handleFetchUser = async () => {
 setIsLoading(true);
 const response = await fetch(`/api/users/${userId}`);
 const data = await response.json();
 setUser(data);
 setIsLoading(false);
 };

 useEffect(() => {
 handleFetchUser();
 }, [userId]);

 return { user, isLoading };
}

Burada dikkat edelim: hook yazsak bile fonksiyon isimlerini handle ile başlatıyoruz. handleFetchUser ne yaptığını açıkça söylüyor. State güncelleme sorumluluğu burada.

// components/UserCard/UserCard.tsx
type UserCardProps = {
 userId: string;
};

 export function UserCard({ userId }: UserCardProps) {
 const { user, isLoading } = useUser(userId);

 if (isLoading) {
 return <div>Yükleniyor...</div>;
 }

 if (!user) {
 return <div>Kullanıcı bulunamadı.</div>;
 }

 return (
 <div className="p-4 border rounded">
 <h2 className="text-lg font-bold">{user.name}</h2>
 <p>{user.email}</p>
 </div>
 );
}

Artık hook veri getiriyor, component sadece render ediyor ve sorumluluklar net

💡 Ben burada makaleyi çok uzatmamak adına, “Loading, error gibi state’ler nasıl daha iyi yönetilir” anlatmayacağım ama bununla alakalı daha önce bir makale yazmıştım. Loading, Error ve Empty State Nasıl Daha İyi Yönetilir?

🪝 Custom Hooks: Bussinnes Logic’leri Component’ten Ayıralım

Custom hook’lar, component mantığını yeniden kullanılabilir fonksiyonlara ile kullanmamızı sağlar. Component sadece render işine odaklanırken, tüm state yönetimi ve side effect’ler hook’larda toplanır.

Hook yazarken şu kurallara uyuyoruz:

★ Hook adı her zaman use ile başlamalı
★ Tek bir sorumluluğu olmalı
★ Component'ten bağımsız çalışabilmeli
★ Return değeri açık ve anlaşılır olmalı

Örnek: Form Yönetimi Custom Hook

// hooks/useForm.ts
import { useCallback, useState } from "react";

export function useForm<T extends Record<string, unknown>>(
 initialValues: T,
 onSubmit: (values: T) => Promise<void>
) {
 const [values, setValues] = useState<T>(initialValues);
 const [errors, setErrors] = useState<Partial<Record<keyof T, string>>>({});
 const [isSubmitting, setIsSubmitting] = useState(false);

 const handleChange = useCallback(
 (name: keyof T, value: T[keyof T]) => {
 setValues((prev) => ({ ...prev, [name]: value }));

 if (errors[name]) {
 setErrors((prev) => {
 const newErrors = { ...prev };
 delete newErrors[name];
 return newErrors;
 });
 }
 },
 [errors]
 );

 const handleSubmit = useCallback(
 async (e: React.FormEvent) => {
 e.preventDefault();
 setIsSubmitting(true);

 try {
 await onSubmit(values);
 } catch (error: unknown) {
 if (error instanceof Error) {
 setErrors({ general: error.message } as Partial<Record<keyof T, string>>);
 }
 } finally {
 setIsSubmitting(false);
 }
 },
 [values, onSubmit]
 );

 const handleReset = useCallback(() => {
 setValues(initialValues);
 setErrors({});
 }, [initialValues]);

 return {
 values,
 errors,
 isSubmitting,
 handleChange,
 handleSubmit,
 handleReset,
 };
}

Bu hook’u bir form component’inde kullanalım:

// components/ContactForm/ContactForm.tsx
import { useForm } from "@/modules/shared/hooks/useForm";

import { Button } from "../Button";
import { Input } from "../Input";

export function ContactForm() {
 const { values, errors, isSubmitting, handleChange, handleSubmit } = useForm(
 { name: "", email: "", message: "" },
 async (values) => {
 await fetch("/api/contact", {
 method: "POST",
 body: JSON.stringify(values),
 });
 }
 );

 return (
 <form onSubmit={handleSubmit}>
 <Input
 name="name"
 value={values.name}
 onChange={(e) => handleChange("name", e.target.value)}
 error={errors.name}
 label="Ad Soyad"
 />
 <Input
 name="email"
 value={values.email}
 onChange={(e) => handleChange("email", e.target.value)}
 error={errors.email}
 label="E-posta"
 />
 <Button type="submit" disabled={isSubmitting}>
 Gönder
 </Button>
 </form>
 );
}

★ Form mantığı tamamen useForm hook'unda

★ Component sadece UI'ı render ediyor

★ Aynı hook'u farklı formlarda kullanabiliriz

📛 İsimlendirme standartları

Tutarlı isimlendirme, kodun okunabilirliğini ve bakımını artırır. Benim en sık uyguladığım isimlendirme standartlarını paylaşayım.

Handler fonksiyonları

Handler fonksiyonları her zaman handle prefix'i ile başlamalı ve hangi aksiyonu tetiklediği açıkça belirtilmeli:

// ❌ Kötü: Ne yaptığı belirsiz
const change = () => {};
const click = () => {};
const update = (data) => {};

// ✅ İyi: Hangi aksiyonu tetiklediği açık
const handleEmailChange = (value: string) => {};
const handleSubmitForm = (e: React.FormEvent) => {};
const handleToggleModal = () => {};
const handleProductSelect = (productId: string) => {};

İsimlendirme şeması

★ handle + Aksiyon + Detay formatı (örn: handlePriceChange, handleCategorySelect)

★ Boolean değişkenler is, has, should ile başlar (örn: isLoading, hasError, shouldRender)

★ Callback prop'ları on ile başlar (örn: onClick, onSubmit, onProductSelect)

★ Custom hook'lar use ile başlar (örn: useUser, useForm, useProductFilters)

Bu sayede başka bir component içinden hook’u kullandığımızda hangi hook’tan ne action geldiğini anlayabiliriz. Editörde CMD (CTRL) + Click yapmaktan kaçınmak için 😁

🚫 Short-If Kullanımından kaçınmak

Şu yapı çok sık görülür:

// ❌ Tehlikeli: count 0 olduğunda ekrana "0" yazılır
{count && <div>{count} ürün</div>}

// ❌ Okunaksız: iç içe && kullanımı
{user && user.isPremium && user.credits > 0 && <PremiumBadge />}

Bu yaklaşımın sorunları:

★ products.length 0 olduğunda JSX içinde 0 render edilir

★ Birden fazla koşul olduğunda okunabilirlik düşer

★ Falsy değerler (0, "", null, undefined) beklenmedik sonuçlar verir

Guard clause yaklaşımı çok daha temiz:

// ✅ İyi: Erken return ile guard clause
export function ProductList({ products }: { products: Product[] }) {
 if (!products || products.length === 0) {
 return <EmptyState message="Henüz ürün bulunmuyor" />;
 }

 return (
 <div>
 <div>Toplam {products.length} ürün</div>
 <div className="product-grid">
 {products.map((product) => (
 <ProductCard key={product.id} product={product} />
 ))}
 </div>
 </div>
 );
}

Bana kalırsa buradaki mühim konu, bir component dosyasını okurken sayfayı ne kadar çok scroll ettiğimiz. Eğer bir component’i separate etmek yerine her şeyi tek yerde yazıyorsak ve bu durum bizim kodu okumamızı zorlaştırıyorsa, o zaman bir şeyler yolunda gitmiyor demektir. Short if kullanıp bir de else blog varsa ve orada da büyük bir JSX render ediyorsak o zaman bende if içinde olan ve else içinde olan kısım separate edilmeli

🏗️ Props Tasarımı

Reusable bir component’in ne kadar kullanışlı olacağı, büyük ölçüde propslarının ne kadar iyi tasarlandığına bağlıdır.

Composition Pattern: Children

// ✅ Flexible: Children pattern
function Card({
 children,
 variant = "default",
}: {
 children: React.ReactNode;
 variant?: "default" | "elevated" | "bordered";
}) {
 return (
 <div className={`card card--${variant}`}>
 {children}
 </div>
 );
}

// Kullanım: İstediğimiz içeriği koyabiliriz
<Card variant="elevated">
 <h2>Başlık</h2>
 <p>İçerik</p>
 <Button>Aksiyon</Button>
</Card>

Büyüyen projelerde reusable component yazmanın en kritik kısmı klasör organizasyonudur. Feature-based (domain-driven) bir yapı öneriyorum:

Feature based — domain driven klasör yapısı
src/
├── modules/
│ ├── product/
│ │ ├── components/
│ │ │ ├── ProductCard/
│ │ │ │ ├── ProductCard.tsx
│ │ │ │ ├── ProductCard.module.scss
│ │ │ │ ├── ProductCard.test.tsx
│ │ │ │ └── index.ts
│ │ │ ├── ProductList/
│ │ │ └── index.ts
│ │ ├── hooks/
│ │ │ ├── useProduct.ts
│ │ │ └── index.ts
│ │ ├── types/
│ │ │ └── product.types.ts
│ │ └── index.ts
│ ├── cart/
│ ├── user/
│ └── shared/
│ ├── components/
│ │ ├── Button/
│ │ ├── Input/
│ │ └── Modal/
│ ├── hooks/
│ └── utils/
└── ...

Her component kendi klasöründe şu dosyaları içerir:

ProductCard/
├── ProductCard.tsx # Ana component
├── ProductCard.module.scss # Component-scoped stiller
├── ProductCard.test.tsx # Unit testler
├── ProductCard.stories.tsx # Storybook stories
└── index.ts # Named export barrel file

index.ts dosyası sadece export içerir:

// index.ts
export { ProductCard } from "./ProductCard";

Bu yapı sayesinde import’lar temiz olur:

// ✅ Temiz import
import { ProductCard } from "@/modules/product/components/ProductCard";

// ❌ Kötü import
import { ProductCard } from "@/modules/product/components/ProductCard/ProductCard";

🎨 Styling: CSS Modules ve SCSS

Global stiller yerine component-scoped bir styling stratejisi benimsemek reusable component yazmanın vazgeçilmez parçasıdır. CSS Modules ile SCSS birleşimi bu konuda oldukça güçlü bir çözüm sunar.

CSS Modules, her component için izole bir stil alanı oluşturur. Class isim çakışmaları yaşanmaz, global scope’u kirletmezsiniz ve component silindiğinde stilleri de beraberinde gider.

SCSS Değişkenleri ve Mixins

Önce global design token’larımızı ve mixinlerimizi tanımlayalım:

// styles/_variables.scss
:root {
 --color-primary: #3b82f6;
 --color-primary-dark: #2563eb;
 --color-secondary: #6b7280;
 --color-danger: #ef4444;
 --color-success: #10b981;

 --spacing-xs: 4px;
 --spacing-sm: 8px;
 --spacing-md: 16px;
 --spacing-lg: 24px;
 --spacing-xl: 32px;

 --border-radius-sm: 4px;
 --border-radius-md: 8px;
 --border-radius-lg: 12px;

 --font-size-sm: 0.875rem;
 --font-size-md: 1rem;
 --font-size-lg: 1.125rem;
}
// styles/_mixins.scss
@mixin flex-center {
 display: flex;
 align-items: center;
 justify-content: center;
}

@mixin responsive($breakpoint) {
 @if $breakpoint == "sm" {
 @media (max-width: 640px) {
 @content;
 }
 } @else if $breakpoint == "md" {
 @media (max-width: 768px) {
 @content;
 }
 } @else if $breakpoint == "lg" {
 @media (max-width: 1024px) {
 @content;
 }
 }
}

@mixin transition($property: all, $duration: 0.2s) {
 transition: $property $duration ease-in-out;
}
Mixin’leri ve değişkenleri oluştururken en önemli konu sonradan ne olduğunu hatırlayabileceğimiz isme sahip olması

Component-Scoped SCSS Module

// Button.module.scss
@use "@/styles/variables" as *;
@use "@/styles/mixins" as *;

.button {
 @include flex-center;
 @include transition(background-color);
 padding: var(--spacing-sm) var(--spacing-md);
 border: none;
 border-radius: var(--border-radius-md);
 font-size: var(--font-size-md);
 font-weight: 500;
 cursor: pointer;

 &:disabled {
 opacity: 0.6;
 cursor: not-allowed;
 }

 // BEM-benzeri modifier'lar CSS Modules ile
 &.primary {
 background-color: var(--color-primary);
 color: white;

 &:hover:not(:disabled) {
 background-color: var(--color-primary-dark);
 }
 }

 &.secondary {
 background-color: transparent;
 color: var(--color-primary);
 border: 2px solid var(--color-primary);

 &:hover:not(:disabled) {
 background-color: var(--color-primary);
 color: white;
 }
 }

 &.sm {
 padding: var(--spacing-xs) var(--spacing-sm);
 font-size: var(--font-size-sm);
 }

 &.lg {
 padding: var(--spacing-md) var(--spacing-lg);
 font-size: var(--font-size-lg);
 }
}
// Button.tsx
import clsx from "clsx";
import styles from "./Button.module.scss";

type ButtonProps = {
 variant?: "primary" | "secondary";
 size?: "sm" | "md" | "lg";
 isLoading?: boolean;
 children: React.ReactNode;
 className?: string;
} & React.ButtonHTMLAttributes<HTMLButtonElement>

export function Button({
 variant = "primary",
 size = "md",
 isLoading = false,
 children,
 className,
 disabled,
 ...rest
}: ButtonProps) {
 return (
 <button
 className={clsx(
 styles.button,
 styles[variant],
 size !== "md" && styles[size],
 className
 )}
 disabled={disabled || isLoading}
 {...rest}
 >
 {isLoading ? <span>Yükleniyor...</span> : children}
 </button>
 );
}

Burada dikkat etmemiz gereken noktalar:

★ clsx ile conditional class'ları yönetiyoruz. Basit ama önemli bir paket, bu sayede class isimlerini bileştirirken kulalnığımız, short-if’lerden kaçınmış oluyoruz

★ Dışarıdan gelen className prop'u ile override imkanı sağlıyoruz

★ Native HTML attribute'larını ...rest ile geçiriyoruz

★ isLoading ve disabled mantığını birleştiriyoruz

🧼 Kod Kalitesi: ESLint Kuralları

Kod okunabilirliği ve tutarlılığı reusable component kadar önemlidir. Birkaç kritik ESLint paketi ile bu standardı otomatik hale getirelim.

eslint-plugin-simple-import-sort

Import’ları otomatik sıralar ve dosyaları çok daha temiz hale getirir:

npm install --save-dev eslint-plugin-simple-import-sort
// .eslintrc.js
module.exports = {
 plugins: ["simple-import-sort"],
 rules: {
 "simple-import-sort/imports": [
 "error",
 {
 groups: [
 // 1. React ve framework importları
 ["^react", "^next"],
 // 2. External paketler
 ["^@?\\w"],
 // 3. Internal absolute importlar
 ["^@/"],
 // 4. Parent importlar
 ["^\\.\\."],
 // 5. Sibling importlar
 ["^\\."],
 // 6. Style importları
 ["^.+\\.s?css$"],
 ],
 },
 ],
 "simple-import-sort/exports": "error",
 },
};
Ben bu plugini uzun yıllardır kullanıyorum. Bu sayede importlar sıralı oluyor her componenet aynı şekilde görünüyor. Alışması biraz zaman alıyor sadece

eslint-plugin-react-hooks

Custom hook yazarken dependency dizilerini yanlış yazmak memory leak’e yol açar:

npm install --save-dev eslint-plugin-react-hooks
module.exports = {
 plugins: ["react-hooks"],
 rules: {
 "react-hooks/rules-of-hooks": "error",
 "react-hooks/exhaustive-deps": "warn",
 },
};

eslint-plugin-import

Named export standardını zorunlu hale getirmek için:

npm install --save-dev eslint-plugin-import
module.exports = {
 plugins: ["import"],
 rules: {
 "import/prefer-default-export": "off",
 "import/no-default-export": "error",
 },
};

Neden named export?
Dosya ismiyle component isminin eşleşmesini garanti eder, IDE’lerin auto-import özelliği mükemmel çalışır ve refactoring sırasında isim değişikliklerini tüm projede güvenle yapabilirsiniz.

✍️ Editor Standartları: EditorConfig ve Prettier

ESLint kodu analiz ederken, EditorConfig ve Prettier kodu biçimlendirir. Bu ikisini birlikte kullanmak ekip içinde tam tutarlılık sağlar.

EditorConfig

.editorconfig dosyası, farklı editor'larda (VSCode, WebStorm, Vim) tutarlı boşluk ve satır sonu ayarlarını garantiler:

# .editorconfig
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{json,yml,yaml}]
indent_size = 2

Prettier

npm install --save-dev prettier eslint-config-prettier
// .prettierrc
{
 "semi": true,
 "singleQuote": false,
 "tabWidth": 2,
 "trailingComma": "es5",
 "printWidth": 100,
 "bracketSpacing": true,
 "arrowParens": "always"
}

Prettier’i ESLint ile çakışmadan kullanmak için eslint-config-prettier'ı extends array'inin sonuna ekliyoruz:

// .eslintrc.js
module.exports = {
 extends: [
 "eslint:recommended",
 "plugin:react/recommended",
 "plugin:react-hooks/recommended",
 "prettier", // Her zaman en sona
 ],
};

VSCode Ayarları

.vscode/settings.json:

{
 "editor.formatOnSave": true,
 "editor.defaultFormatter": "esbenp.prettier-vscode",
 "editor.codeActionsOnSave": {
 "source.fixAll.eslint": true
 },
 "eslint.validate": [
 "javascript",
 "javascriptreact",
 "typescript",
 "typescriptreact"
 ]
}

Artık her kayıt işleminde dosyalarınız otomatik biçimlenir ve import’lar sıralanır.

🧱 Component Parçalama Mantığı

Büyük bir component gördüğümüzde genelde şöyle olur: 300+ satır, bir sürü state, iç içe JSX blokları. Bu noktada şunu yapıyoruz:

★ Tekrar eden UI parçalarını ayırıyoruz

★ Mantıksal blokları alt component yapıyoruz

★ State’i en üstte tutup aşağı props olarak indiriyoruz

// ❌ Monolitik: Her şey tek component'te
function ProductPage() {
 return (
 <div>
 <div className="header">
 <img src={product.image} />
 <h1>{product.name}</h1>
 </div>
 <div className="details">
 <p>{product.description}</p>
 <span>{product.price} ₺</span>
 </div>
 <div className="reviews">
 {reviews.map((review) => (
 <div key={review.id}>{review.text}</div>
 ))}
 </div>
 </div>
 );
}

// ✅ Parçalanmış: Her component kendi sorumluluğunda
function ProductPage() {
 return (
 <div>
 <ProductHeader product={product} />
 <ProductDetails product={product} />
 <ProductReviews productId={product.id} />
 </div>
 );
}

Bu yapı test edilebilirliği artırır, reusability sağlar ve kodun zihinsel yükünü azaltır.

🔮 Sonraki Adımlarda Bakabileceğiniz Konular

Bu yazıda ele aldığımız konular reusable component yazmak için güçlü bir temel oluşturuyor. Daha ileri gitmek isteyenler için şu konuları araştırmanızı öneririm:

Error Handling ve Error Boundaries

React.memo ve React.useCallback ile optimizasyon

Compound Component Pattern: Daha önce yazdığım React’te Compound Component Pattern (Zustand ile) makalesinde detaylıca ele almıştım.

Virtual Scrolling: Büyük listeler için virtualization kullanımı. Eskiden react-virtualized diye bir paket vardı ama şimdi deprecated durumda. Şuan aktif olarak bu konuda, TanStack’in paketleri güncel gibi görünüyor.

Component Driven Development: Bu konuyu Component Driven Development Nedir? Nasıl Uygulanır? makalesinde detaylıca ele almıştım

Yapay Zeka agent ve skiller: Artık Agentic kodlama yaptığımız için yapay zeka agent ve skillerine kendi kod yazma standartlarımızı öğrettiğimiz SKILL.md ve agent’lar oluşturabiliriz. Bunun için benim en çok kullandığım site skills.sh, bir çok skill var. Skilleri ve agentları yönlendirirken de genelde “awesome”, “wtf”, “clean code” repositoryleri bulup onları kullanıyorum

Örneğin:

📬 Geri Bildirim

Makaleyi yazarken, kaynakları belirleme ve araştırma için GPT 5.4, yazım denetimi için Claude Sonnet 4.6 modelini kullandım. Resimleri üretmek için ise Gemini 3 Pro Preview 2k (Nano Banana Pro) modelini kullandım.

Yazı ile ilgili tavsiye, öneri, eleştirileri dikkate alıyorum. İletişime geçmek isterseniz bana websitemdeki sosyal medya adreslerimden veya Linkedin üzerinden ulaşabilirsiniz.

Sevgiyle kalın, Yasin 🤗

📚 Makaleyi Yazarken Kullandığım Kaynaklar

  1. React Documentation — Reusing Logic with Custom Hooks — Custom hook tasarımı için resmi dokümantasyon
  2. eslint-plugin-simple-import-sort — Import sıralama plugin’i dokümantasyonu
  3. eslint-plugin-react-hooks — React hooks kuralları
  4. Bulletproof React — Proje mimarisi yaklaşımı ve best practices
  5. CSS Modules Documentation — Component-scoped stil yönetimi
  6. Sass Documentation — SCSS değişkenleri ve mixinler
  7. Prettier Documentation — Code formatter konfigürasyonu
  8. EditorConfig — Editor tutarlılığı için
  9. Husky & Lint-Staged — Pre-commit otomasyon
  10. clsx — Conditional class name utility
  11. React Testing Library — Guiding Principles — Test yazımı prensipleri
  12. Compound Component Pattern (Zustand ile) — Compound component detayları
  13. Loading, Error ve Empty State Nasıl Daha İyi Yönetilir? — Daha önceki yazdığım state yönetimi prensipleri ile alakalı makalem
  14. Atomic Design Prensibi — Storybook ile component organizasyonu
  15. Component Driven Development— CDD yaklaşımı ve pratikleri
  16. SOLID Nedir ? Solid Yazılım Prensipleri Nelerdir ? — SOLID presipleri
  17. https://tanstack.com/virtual/latest — Virtualizattion paketi