Blog/react/React ilə E-commerce: Azərbaycan Bazarı üçün Komponent Arxitekturası
react

React ilə E-commerce: Azərbaycan Bazarı üçün Komponent Arxitekturası

B
Baku Stack AI
·23 mart 2026·5 dəq oxuma·17 baxış
react.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ REACT E-COM ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ● atoms/PriceTag ▓
▓ → ₼ formatAZN() ▓
▓ ● molecules/Card ▓
▓ → Badge+Price+Btn ▓
▓ ● organisms/Grid ▓
▓ → ProductCard × N ▓
▓ ● hooks/useCart ▓
▓ → localStorage ✓ ▓
▓ PERF: ▓▓▓▓▓▓▓░░ 78% ▓
▓ memo+lazy+virtual ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

Tap.az, Umico və ya öz e-commerce layihən üçün scalable React komponent arxitekturası necə qurulur? Real kod, real struktur, real təcrübə.

React ilə E-commerce: Azərbaycan Bazarı üçün Komponent Arxitekturası

Salam, developer dostlar! Bu gün Azərbaycan e-commerce bazarı üçün React komponent arxitekturası haqqında danışacağıq — konkret, praktiki və copy-paste edə biləcəyiniz kod nümunələri ilə.

Bakıda hazırda orta və böyük şirkətlərdə (Umico, ABB, Bravo, Kontakt Home) frontend developer tələbi ciddi artıb. LinkedIn-də "React developer Baku" axtarışı etsəniz, 60+ aktiv vakansiya görəcəksiniz. Maaş diapazonu Junior üçün 800-1200 AZN, Middle üçün 1500-2500 AZN, Senior üçün isə 3000-5000+ AZN civarındadır. Bu vakansiyaların əksəriyyətində e-commerce təcrübəsi üstünlük kimi qeyd olunur.

Bəs niyə komponent arxitekturası bu qədər vacibdir?

Problem: Spaghetti Komponentlər

Təsəvvür edin, Kontakt Home kimi bir elektronika mağazası üçün sayt yazırsınız. Əvvəlcə bir ProductPage.jsx faylı yaradırsınız — 500 sətir. Sonra ora filter əlavə edirsiniz — 800 sətir. Sonra AZN/USD valyuta çevirici, karqo kalkulyatoru... və artıq 1500 sətirlik bir monster var əlinizdə.

Bu yanaşma ilə:

  • Yeni developer komandaya qoşulanda 2 həftə fayl oxuyur
  • Bir bug fix 5 yeni bug yaradır
  • Test yazmaq mümkünsüz olur

Həll: Atomic Design + Feature-Based Struktur

Azərbaycan e-commerce layihəsi üçün ən optimal yanaşma Atomic Design prinsipi ilə Feature-Based folder strukturunun birləşməsidir.

Folder Strukturu

src/
├── components/
│   ├── atoms/
│   │   ├── Button/
│   │   ├── PriceTag/
│   │   ├── Badge/
│   │   └── CurrencyDisplay/
│   ├── molecules/
│   │   ├── ProductCard/
│   │   ├── SearchBar/
│   │   ├── CartItem/
│   │   └── FilterChip/
│   ├── organisms/
│   │   ├── ProductGrid/
│   │   ├── Header/
│   │   ├── CartSidebar/
│   │   └── FilterPanel/
│   └── templates/
│       ├── CatalogLayout/
│       └── CheckoutLayout/
├── features/
│   ├── catalog/
│   ├── cart/
│   ├── checkout/
│   └── auth/
├── hooks/
│   ├── useCart.js
│   ├── useCurrency.js
│   └── useLocalStorage.js
├── utils/
│   ├── formatAZN.js
│   └── transliterate.js
└── constants/
    └── regions.js

Bu struktur 50+ komponentlik layihədə belə naviqasiyanı rahat edir.

Real Kod: AZN Qiymət Komponenti

Azərbaycan e-commerce saytının ən əsas atom komponenti — qiymət göstəricisi. Gəlin PriceTag komponentini yazaq:

jsx
// src/components/atoms/PriceTag/PriceTag.jsx import { memo } from 'react'; import { formatAZN } from '../../../utils/formatAZN'; import styles from './PriceTag.module.css'; const PriceTag = memo(({ price, oldPrice, size = 'md', showManat = true }) => { const hasDiscount = oldPrice && oldPrice > price; const discountPercent = hasDiscount ? Math.round(((oldPrice - price) / oldPrice) * 100) : 0; return ( <div className={`${styles.wrapper} ${styles[size]}`}> {hasDiscount && ( <span className={styles.oldPrice}> {formatAZN(oldPrice)} </span> )} <span className={styles.currentPrice}> {formatAZN(price)} {showManat && <span className={styles.currency}></span>} </span> {hasDiscount && ( <span className={styles.discount}>-{discountPercent}%</span> )} </div> ); }); PriceTag.displayName = 'PriceTag'; export default PriceTag;
js
// src/utils/formatAZN.js export const formatAZN = (amount) => { return new Intl.NumberFormat('az-AZ', { minimumFractionDigits: 2, maximumFractionDigits: 2, }).format(amount); }; // formatAZN(1499.9) → "1 499,90"

Bu kiçik atom komponenti layihənin hər yerində istifadə olunacaq — ProductCard, CartItem, OrderSummary hamısı bunu çağırır.

Molecule Səviyyəsi: ProductCard

İndi atom komponentləri birləşdirərək ProductCard molecule yaradaq:

jsx
// src/components/molecules/ProductCard/ProductCard.jsx import PriceTag from '../../atoms/PriceTag/PriceTag'; import Badge from '../../atoms/Badge/Badge'; import Button from '../../atoms/Button/Button'; import { useCart } from '../../../hooks/useCart'; import styles from './ProductCard.module.css'; const ProductCard = ({ product }) => { const { addToCart, isInCart } = useCart(); const { id, name, image, price, oldPrice, inStock, isNew } = product; return ( <article className={styles.card}> <div className={styles.imageWrapper}> <img src={image} alt={name} loading="lazy" /> {isNew && <Badge variant="new">Yeni</Badge>} {!inStock && <Badge variant="outOfStock">Stokda yoxdur</Badge>} </div> <div className={styles.info}> <h3 className={styles.name}>{name}</h3> <PriceTag price={price} oldPrice={oldPrice} /> </div> <Button variant={isInCart(id) ? 'secondary' : 'primary'} onClick={() => addToCart(product)} disabled={!inStock} fullWidth > {isInCart(id) ? 'Səbətdədir ✓' : 'Səbətə at'} </Button> </article> ); }; export default ProductCard;

Diqqət edin: ProductCard heç bir business logic saxlamır. Səbət məntiqi useCart hook-unda, qiymət formatlaması PriceTag-da, vizual badge-lər Badge-dadır. Hər şey öz yerində.

Custom Hook: useCart

Business logic-i komponentlərdən ayırmaq üçün custom hook-lar istifadə edirik:

jsx
// src/hooks/useCart.js import { useCallback, useMemo } from 'react'; import { useLocalStorage } from './useLocalStorage'; export const useCart = () => { const [items, setItems] = useLocalStorage('cart', []); const addToCart = useCallback((product) => { setItems((prev) => { const exists = prev.find((item) => item.id === product.id); if (exists) { return prev.map((item) => item.id === product.id ? { ...item, quantity: item.quantity + 1 } : item ); } return [...prev, { ...product, quantity: 1 }]; }); }, [setItems]); const isInCart = useCallback( (id) => items.some((item) => item.id === id), [items] ); const total = useMemo( () => items.reduce((sum, item) => sum + item.price * item.quantity, 0), [items] ); return { items, addToCart, isInCart, total, itemCount: items.length }; };

Bu hook localStorage ilə işləyir, yəni istifadəçi səhifəni yeniləsə belə səbət itmir. Azərbaycan istifadəçiləri üçün bu kritik feature-dur — internet bağlantısı kəsiləndə data itməməlidir.

Azərbaycana Xas Nüanslar

E-commerce layihəsində Azərbaycan kontekstini nəzərə almaq lazımdır:

  • Valyuta: Həmişə AZN (₼) göstərin, lazım gələrsə USD çevirmə əlavə edin
  • Ünvan sistemi: Bakı rayonları (Nəsimi, Yasamal, Binəqədi...) üçün ayrıca RegionSelector komponenti yazın
  • Ödəniş metodları: Hər layihədə mütləq "Qapıda ödəniş" seçimi olmalıdır — Azərbaycanda alıcıların 60%-dən çoxu bunu seçir
  • Dil dəstəyi: AZ/RU/EN — ən azı bu üç dil. react-i18next istifadə edin
  • Telefon formatı: +994 XX YYY YY YY formatında input mask lazımdır
js
// src/constants/regions.js export const BAKU_REGIONS = [ { id: 'nasimi', label: 'Nəsimi', deliveryFee: 3.00 }, { id: 'yasamal', label: 'Yasamal', deliveryFee: 3.00 }, { id: 'sabunchu', label: 'Sabunçu', deliveryFee: 5.00 }, { id: 'khirdalan', label: 'Xırdalan', deliveryFee: 7.00 }, // ... ];

Performance: Nəyə Diqqət Etməli?

Umico kimi saytda minlərlə məhsul var. Performance üçün:

  1. React.memoProductCard kimi tez-tez render olunan komponentlər üçün
  2. Virtualizationreact-window ilə uzun məhsul siyahıları üçün (1000+ item)
  3. Code Splitting — Checkout səhifəsi lazy load olsun: React.lazy(() => import('./features/checkout'))
  4. Image optimization — WebP format, loading="lazy", responsive srcSet

Bu optimizasiyalar First Contentful Paint-i 40-60% yaxşılaşdıra bilər.

Nəticə

Yaxşı komponent arxitekturası:

  • Yeni developerin onboarding müddətini 2 həftədən 2-3 günə endirir
  • Bug fix vaxtını ortalama 3x azaldır
  • Feature əlavə etməyi asanlaşdırır

Əgər portfolionuzda belə strukturlaşdırılmış bir e-commerce layihəsi varsa, Bakıdakı şirkətlər (Umico, Tap.az, ABB, Bravo online) bunu mütləq qiymətləndirəcək. GitHub-da public repo kimi paylaşın, README-də arxitektura diaqramı çəkin.

Sualınız varsa LinkedIn-də və ya kommentlərdə yazın. Növbəti məqalədə bu arxitekturanın üzərinə state management (Zustand vs Redux Toolkit) əlavə edəcəyik.

Kod yazmağa davam! 🚀

Oxşar məqalələr

react.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ REACT PERF ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ useMemo → cache ▓
▓ useCallback → ref ▓
▓░░░░░░░░░░░░░░░░░░░░░░▓
▓ 10K items: ▓
▓ no memo: 12ms ● ▓
▓ w/ memo: 0.3ms ✓ ▓
▓░░░░░░░░░░░░░░░░░░░░░░▓
▓ QAYDA: ▓
▓ >2ms → useMemo ✓ ▓
▓ <2ms → skip → ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

React-da Performans: useMemo və useCallback — Nə Vaxt Lazımdır?

useMemo və useCallback hər yerə yazmaq reflex olub? Gəl birlikdə anlayaq: bu hook-lar nə vaxt həqiqətən lazımdır, nə vaxt isə əksinə — zərərdir.

react.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ REACT QUERY ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ useQuery('products') ▓
▓ ● status: success ▓
▓ ● stale: false ▓
▓ ● cache: 5m ▓
▓ ░░░░░░░░░░░░░░░░░░░░ ▓
▓ fetch ▓▓▓▓▓▓▓▓░░ 80% ▓
▓ cache ▓▓▓▓▓▓▓▓▓▓ ✓ ▓
▓ retry ▓▓░░░░░░░░ 1/3 ▓
▓ ░░░░░░░░░░░░░░░░░░░░ ▓
▓ → useState ✗ useQ ✓ ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

React Query ilə Server State: useState-dən Qurtuluş Yolu

Hələ də API datanı useState + useEffect ilə idarə edirsən? React Query ilə server state-i necə peşəkar səviyyədə idarə etməyi öyrən.

react.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ REACT / RSC ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ Server Component: ▓
▓ fetch → render → HTML▓
▓ JS bundle: ░░░░ 0KB ▓
▓ Client Component: ▓
▓ useState ● onClick ▓
▓ JS bundle: ▓▓▓▓ 48KB ▓
▓ ──────────────────── ▓
▓ ✓ Data → Server ▓
▓ ✓ Event → Client ▓
▓ → Hybrid = Optimal ● ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

React Server Components — Nə Vaxt İstifadə Etməli, Nə Vaxt Yox?

RSC hər yerə lazım deyil. Bu məqalədə real kod nümunələri ilə Server Components-in nə vaxt performans artırdığını, nə vaxt isə əngəl olduğunu izah edirik.

← Bloqa qayıt