React — istifadəçi interfeyslərini müstəqil bloklardan, yəni komponentlərdən qurmaq üçün JavaScript kitabxanasıdır. Onu 2013-cü ildə Meta (o vaxtkı Facebook) yaradıb və bu gün Facebook, Instagram, WhatsApp Web, Netflix, Airbnb, Discord, həmçinin minlərlə şəxsi kabinet, admin panel və onlayn mağaza React üzərində işləyir. Bu mövzuda React-in hansı problemi həll etdiyini görəcək, eyni kodu "təmiz" JavaScript və React ilə müqayisə edəcək və bütün kursun əsaslandığı əsas ideyalarla tanış olacağıq. Hələlik heç nə quraşdırmaq lazım deyil — layihəni növbəti mövzuda yaradacağıq.
Problem: DOM ilə əl ilə işləmək
Vanilla JavaScript-də sadə sayğacdan başlayaq. Markup:
<p>Clicks: <span id="count">0</span></p>
<button id="inc">+1</button>
<button id="reset">Reset</button>Və onu "canlandıran" skript:
let count = 0
const countEl = document.querySelector('#count')
const incBtn = document.querySelector('#inc')
const resetBtn = document.querySelector('#reset')
incBtn.addEventListener('click', () => {
count++
countEl.textContent = count // DOM-u yeniləməyi unutmayın!
})
resetBtn.addEventListener('click', () => {
count = 0
countEl.textContent = count // burada da
})Kod işləyir, amma diqqət edin: məlumat (count) və onun ekranda göstərilməsi (countEl.textContent) ayrı-ayrı yaşayır və onları hər handler-də əl ilə sinxronlaşdırmaq lazımdır. Sabah sayğacın dəyərini saytın başlığında da göstərmək tələb olunsa, count-un dəyişdiyi bütün yerləri tapıb ora ikinci elementin yenilənməsini əlavə etməli olacaqsınız. Bir yeri unutdunuz — interfeys köhnəlmiş məlumatı göstərir.
Dinamik siyahılarda iş daha da çətinləşir. Budur, əlavə etmə və silmə imkanı olan tapşırıqlar siyahısı:
const tasks = ['Learn JSX', 'Build a counter']
const list = document.querySelector('#tasks')
const form = document.querySelector('#task-form')
const input = document.querySelector('#new-task')
function renderTasks() {
list.innerHTML = tasks
.map((task, i) => `<li>${task} <button data-index="${i}">×</button></li>`)
.join('')
}
form.addEventListener('submit', (e) => {
e.preventDefault()
tasks.push(input.value)
input.value = ''
renderTasks() // hər dəyişiklikdən sonra — əl ilə yenidən çəkmək
})
list.addEventListener('click', (e) => {
if (e.target.matches('button')) {
tasks.splice(Number(e.target.dataset.index), 1)
renderTasks()
}
})
renderTasks()Bu yanaşmanın birdən bir neçə problemi var:
- Hər şey tamamilə yenidən çəkilir.
innerHTMLbütün<li>elementlərini silib yenidən yaradır: uzun siyahılarda bu yavaşdır, içəridə input sahələri olsaydı, onlar fokusu və yazılmış mətni itirərdi. - XSS zəifliyi. İstifadəçi
<img src=x onerror="alert('hacked')">daxil etsə, sətirinnerHTML-ə əsl HTML kimi düşəcək və skript icra olunacaq. - Yeniləməni unutmaq asandır. Məlumatın hər dəyişikliyi mütləq
renderTasks()çağırışı ilə bitməlidir. - Məntiq səpələnib. Markup HTML faylında, şablon sətri JS-də, handler-lər delegasiya və
data-indexvasitəsilə — interfeysin necə işlədiyini anlamaq üçün hər üç yeri eyni anda yadda saxlamalısınız.
Eyni kod React ilə
İndi React-də sayğaca baxaq. Sintaksisi (JSX, useState) növbəti mövzularda ətraflı öyrənəcəyik — hələlik ideyanın özü vacibdir.
import { useState } from 'react'
function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Clicks: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
)
}Burada nə bir querySelector, nə də bir textContent var. Biz count-un istənilən dəyəri üçün interfeysin necə görünməli olduğunu təsvir etdik, düyməyə basanda isə yalnız setCount ilə məlumatı dəyişirik. Qalanını React özü edir: Counter funksiyasını yenidən çağırır, nəticəni əvvəlki ilə müqayisə edir və DOM-da yalnız <p> içindəki mətni yeniləyir. Dəyər başlıqda da lazım olsa, markup-da uyğun yerə {count} yazmaq kifayətdir — yeniləmə avtomatik baş verəcək.
React-də tapşırıqlar siyahısı:
import { useState } from 'react'
function TaskList() {
const [tasks, setTasks] = useState([
{ id: 1, title: 'Learn JSX' },
{ id: 2, title: 'Build a counter' },
])
const [text, setText] = useState('')
function handleSubmit(e) {
e.preventDefault()
setTasks([...tasks, { id: crypto.randomUUID(), title: text }])
setText('')
}
return (
<form onSubmit={handleSubmit}>
<input value={text} onChange={(e) => setText(e.target.value)} />
<button>Add</button>
<ul>
{tasks.map((task) => (
<li key={task.id}>
{task.title}{' '}
<button type="button" onClick={() => setTasks(tasks.filter((t) => t.id !== task.id))}>
×
</button>
</li>
))}
</ul>
</form>
)
}Markup, məlumat və handler-lər artıq bir yerdə toplanıb. Tapşırıq əlavə edəndə React DOM-da yalnız bir yeni <li> yaradacaq, qalan elementlərə toxunmayacaq. <img src=x onerror=...> sətri isə adi mətn kimi göstəriləcək: React {} vasitəsilə çıxarılan hər şeyi ekranlaşdırır (escape edir), ona görə də bu növ XSS hücumları standart olaraq mümkün deyil.
Deklarativ UI: UI = f(state)
React-in əsas ideyası UI = f(state) düsturuna sığır: interfeys vəziyyətin (state) funksiyasıdır. Siz "elementi tap, düyməni gizlət, salamlamanı göstər" kimi təlimatlar yazmırsınız, əksinə, hər mümkün vəziyyətdə ekranda nə olmalı olduğunu təsvir edirsiniz. Bu üslub deklarativ, əl ilə verilən DOM əmrləri isə imperativ adlanır.
İmperativ (vanilla JS):
function updateHeader(user) {
if (user) {
loginBtn.hidden = true
greeting.textContent = `Welcome back, ${user.name}!`
greeting.hidden = false
} else {
loginBtn.hidden = false
greeting.hidden = true
}
}Deklarativ (React):
function Header({ user }) {
if (!user) {
return <button>Log in</button>
}
return <p>Welcome back, {user.name}!</p>
}İkinci variantda giriş düyməsi ilə salamlamanın eyni anda göründüyü "sınıq" vəziyyətə düşmək mümkün deyil: user-in hər dəyəri üçün tam olaraq bir nəticə təsvir olunub.
| İmperativ yanaşma | Deklarativ yanaşma | |
|---|---|---|
| Nə yazırsınız | Addımlar: tap, dəyiş, gizlət | Hər vəziyyət üçün nəticə |
| DOM-u kim yeniləyir | Siz, əl ilə | React |
| Məlumat haqqında həqiqət harada | Dəyişənlər və DOM arasında səpələnib | Yalnız state-də |
| Tipik baglar | Unudulmuş yeniləmə, uyğunsuzluq | Nadir: ekran həmişə məlumatdan irəli gəlir |
Komponentlər və biristiqamətli məlumat axını
Komponent interfeysin bir hissəsini qaytaran funksiyadır. Kiçik komponentlərdən, konstruktor hissələri kimi, böyükləri yığılır: düymə → məhsul kartı → kataloq → səhifə. Eyni komponenti müxtəlif məlumatlarla dəfələrlə istifadə etmək olar.
import { useState } from 'react'
function ProductCard({ title, price, onAdd }) {
return (
<article className="card">
<h3>{title}</h3>
<p>{price} AZN</p>
<button onClick={onAdd}>Add to cart</button>
</article>
)
}
function Shop() {
const [cartCount, setCartCount] = useState(0)
return (
<main>
<header>Cart: {cartCount}</header>
<ProductCard title="Laptop" price={1899} onAdd={() => setCartCount(cartCount + 1)} />
<ProductCard title="Mouse" price={35} onAdd={() => setCartCount(cartCount + 1)} />
</main>
)
}Komponentlər ağac əmələ gətirir:
Shop ← cartCount state-ini saxlayır
├── header ← cartCount-u göstərir
├── ProductCard ← title, price, onAdd dəyərlərini props vasitəsilə alır
└── ProductCardReact-də məlumat bir istiqamətdə — yuxarıdan aşağı axır: valideyn Shop kartlara məlumatı props (komponentin xassələri) vasitəsilə ötürür. Kart cartCount-u özü dəyişə bilməz — o, yalnız valideynin ona ötürdüyü onAdd funksiyasını çağırır, valideyn isə öz state-ini dəyişir. Bu biristiqamətli məlumat axını sayəsində məlumatın harada saxlandığı və onu kimin dəyişdiyi həmişə aydındır: bagın səbəbini tapmaq üçün ağacla yuxarı qalxmaq kifayətdir.
Virtual DOM və reconciliation: intuisiya
JSX yazanda React DOM elementlərini dərhal yaratmır. Əvvəlcə adi JavaScript obyekti alınır — ekranda nə göstərilməli olduğunun təsviri:
// count = 0 olanda JSX <p className="note">Clicks: {count}</p> bu obyektə çevrilir:
{
type: 'p',
props: { className: 'note', children: ['Clicks: ', 0] },
key: null,
}Belə obyektlərin ağacını çox vaxt virtual DOM adlandırırlar. Obyekt yaratmaq çox ucuzdur, əsl DOM-u dəyişmək isə bahalıdır: brauzer stilləri, yerləşməni yenidən hesablamalı və səhifəni yenidən çəkməlidir. Ona görə də state dəyişəndə React belə işləyir:
- Komponentin funksiyasını yenidən çağırır və yeni obyekt ağacı alır.
- Onu əvvəlki ağacla müqayisə edir — bu proses reconciliation (uzlaşdırma) adlanır.
- Əsl DOM-a yalnız tapılmış fərqləri tətbiq edir.
Render 1 (count = 0) Render 2 (count = 1)
<div> <div>
<p>Clicks: 0</p> <p>Clicks: 1</p> ← yalnız mətn dəyişib
<button>+1</button> <button>+1</button>
</div> </div>DOM-da bir mətn düyünü dəyişəcək, düymələr isə eyni elementlər olaraq qalacaq — eyni fokus və eyni handler-lərlə. Render və commit mərhələlərini "React ekranı necə yeniləyir" mövzusunda ətraflı araşdıracağıq.
💡 Virtual DOM-un əsas dəyəri "nəyin bahasına olursa olsun sürət" deyil, sadə proqramlaşdırma modelidir: siz hər dəfə interfeysi bütövlükdə təsvir edirsiniz, DOM-dakı minimal dəyişiklikləri isə React öz üzərinə götürür.
2026-cı ildə React ekosistemi
React məhz interfeys üçün kitabxanadır. Marşrutlaşdırma, məlumatların yüklənməsi, formalar və build ayrı alətlərlə həll olunur və illər ərzində React ətrafında nəhəng ekosistem formalaşıb. Aktual versiya React 19-dur (kurs yazılan zaman 19.3): funksional komponentlər, hook-lar, formalar üçün Actions, təkrar render-ləri avtomatik optimallaşdıran stabil React Compiler.
| Tapşırıq | 2026-cı ildə nə ilə həll edirlər |
|---|---|
| SPA: şəxsi kabinet, admin panel, dashboard | React + Vite (bu kurs) |
| SEO və server render-i olan sayt, full-stack | Next.js, framework rejimində React Router |
| iOS/Android mobil tətbiqlər | React Native + Expo |
| SPA-da marşrutlaşdırma | React Router, TanStack Router |
| Server məlumatları və keş | TanStack Query |
| Qlobal state | Zustand, Redux Toolkit |
| Formalar və validasiya | React Hook Form + Zod |
| Testlər | Vitest + React Testing Library |
Bu cədvəldəki demək olar ki, hər şeyi kursda öyrənəcəksiniz. React bilgisi həm Next.js-ə, həm də React Native ilə mobil proqramlaşdırmaya yol açır — komponent, props və state prinsipləri orada da eynidir.
Tipik səhvlər
1. React komponentinin içində DOM-u əl ilə dəyişmək. React sizin dəyişikliklərinizdən xəbərsizdir və növbəti render-də onları üzərindən yazacaq.
// ❌ Pis: React-dən yan keçirik
function handleClick() {
document.querySelector('#count').textContent = count + 1
}
// ✅ Yaxşı: məlumatı dəyişirik, DOM-u React özü yeniləyəcək
function handleClick() {
setCount(count + 1)
}2. Məlumatı DOM-da saxlamaq və oradan oxumaq. Number(countEl.textContent) + 1 kimi kod DOM-u həqiqət mənbəyinə çevirir. React-də həqiqət mənbəyi state-dir, DOM isə onu sadəcə əks etdirir.
3. Adi dəyişənin ekranı yeniləyəcəyini gözləmək. let count = 0 elan edib handler-də count++ yazsanız, dəyər dəyişəcək, amma React bundan xəbər tutmayacaq və komponenti yenidən render etməyəcək. Zamanla dəyişən məlumat üçün useState lazımdır — onu state bölməsində ətraflı öyrənəcəyik.
4. React-i "hər şeyi hazır olan" framework hesab etmək. React-də daxili router, HTTP klient və ya forma validasiyası yoxdur. Bu çatışmazlıq deyil, şüurlu seçimdir: tapşırığa uyğun sınanmış kitabxanaları qoşursunuz.
5. React-ə JavaScript-i yaxşı bilmədən başlamaq. Yeni başlayanların "React problemlərinin" çoxu əslində JS-dəki boşluqlardır. Kursdan əvvəl arrow funksiyaları, destrukturizasiyanı, spread operatorunu, map/filter massiv metodlarını, import/export modullarını, şablon sətirlərini, ternar operatoru və async/await-i inamla bildiyinizə əmin olun.
Xülasə
- React interfeysləri komponentlərdən qurmaq üçün kitabxanadır; marşrutlaşdırma, məlumat və formalar ekosistemin ayrı kitabxanaları ilə həll olunur.
- DOM ilə əl ilə iş hər handler-də məlumatı və ekranı sinxronlaşdırmağı tələb edir — buradan uyğunsuzluq, artıq yenidən çəkmələr və
innerHTMLvasitəsilə XSS yaranır. - React deklarativdir: UI = f(state). Siz hər vəziyyət üçün nəticəni təsvir edirsiniz, DOM-u isə React özü yeniləyir.
- Komponentlər markup qaytaran funksiyalardır; onlardan interfeys ağacı yığılır.
- Məlumat props vasitəsilə yuxarıdan aşağı axır, yuxarıya isə handler funksiyalarının çağırışları ötürülür.
- Virtual DOM və reconciliation əsl DOM-da yalnız həqiqətən dəyişəni yeniləməyə imkan verir.
- 2026-cı ilin aktual stack-i: React 19, SPA üçün Vite, full-stack üçün Next.js və React Router, mobil tətbiqlər üçün React Native.
Praktika
- Birinci bölmədəki vanilla sayğaca
count-un göstərildiyi ikinci yer əlavə edin (məsələn, "Clicks: 0" mətni olan<h1>). Neçə sətri dəyişməli oldunuz? React versiyasında nəyi dəyişmək lazım olacağını sözlə təsvir edin. - İstənilən onlayn mağazanı açın və məhsul səhifəsinin komponent ağacını mətn şəklində çəkin (başlıq, qalereya, qiymət bloku, rəylər və s.). "Səbətdəki məhsulların sayı" state-inin hansı komponentdə saxlanmalı olduğunu qeyd edin.
- Vanilla tapşırıqlar siyahısına fikrən
<b>bold</b>sətrini daxil edin. Səhifə nə göstərəcək? Bəs React versiyası? Fərqi izah edin. - Baku şəhəri üçün hava widget-i layihələndirin: mümkün vəziyyətləri (yüklənmə, xəta, məlumat alınıb), komponentləri və onların props-larını sadalayın. Hər vəziyyət üçün "psevdo-JSX" ilə ekranda nə olmalı olduğunu yazın.
💡 4-cü tapşırıqda işlək kod lazım deyil — vacib olan vəziyyətlərlə düşünməyi öyrənməkdir: "belə məlumat olanda ekran belə görünür".