Гузариш ба мундариҷа
Мавзӯи 6 аз 13
Назария

React саҳифаро чӣ тавр нав мекунад

Чаро ин муҳим аст

Дар мавзӯъҳои гузашта мо setCount(count + 1) менавиштем, ва «React компонентро аз нав мекашид». Вақти он расид, ки фаҳмем дар ин вақт маҳз чӣ рух медиҳад. Бе ин React ҷоду мемонад, ва аксари хатоҳои навомӯзон — «чаро экран нав нашуд», «чаро қимат кӯҳна аст», «чаро майдон тоза нашуд» — нофаҳмо мемонанд. Баъд аз ин мавзӯъ шумо метавонед пеш аз иҷрои код пешгӯӣ кунед, ки React чӣ мекунад.

Се қадам: оғоз, кашидан, татбиқ

Ҳар навсозии экран дар React аз се қадам мегузарад:

  1. Оғоз (trigger). Чизе навсозӣ мехоҳад: кашидани аввал root.render(...) ё даъвати функсияи set… аз useState.
  2. Кашидан (render). React функсия-компонентҳоро даъват мекунад. Ҳар кадом JSX бармегардонад — тасвири он чи бояд дар экран бошад. Худи саҳифа дар ин қадам ҳоло тағйир намеёбад.
  3. Татбиқ (commit). React тасвири навро бо пешина муқоиса мекунад ва дар DOM-и ҳақиқӣ танҳо он чиро, ки фарқ мекунад, иваз мекунад. Баъд аз ин эффектҳо (useEffect) оғоз мешаванд.

«Кашидан» дар React — ин кашидани пикселҳо не, балки танҳо даъвати функсияи шумост.

JSX чӣ бармегардонад

JSX — HTML нест. Ҷамъоваранда ҳар тегро ба даъвати React.createElement табдил медиҳад, ва он объекти оддӣ бармегардонад:

const element = <h1 className="title">Салом</h1>;
// баъд аз ҷамъоварӣ:
const element = React.createElement("h1", { className: "title" }, "Салом");
// ин объекти тақрибан чунин намуд аст:
// { type: "h1", props: { className: "title", children: "Салом" } }

Дарахти чунин объектҳоро DOM-и маҷозӣ (virtual DOM) меноманд. Сохтани объектҳо хеле арзон аст, вале иваз кардани саҳифаи ҳақиқӣ гарон аст: браузер бояд ҷойгиршавиро аз нав ҳисоб кунад ва пикселҳоро аз нав кашад. Барои ҳамин React ҳар дафъа дарахти нави сабукро пурра месозад, ва ба DOM-и ҳақиқӣ ислоҳоти ҳадди ақал медарорад.

Муқоисаи дарахтҳо

Муқоисаи дарахти кӯҳна ва навро reconciliation (мувофиқасозӣ) меноманд. Қоидаҳо оддӣ:

  • унсури ҳамон навъ дар ҳамон ҷой — React гиреҳи DOM-ро мегузорад ва танҳо атрибутҳо ва матни тағйирёфтаро иваз мекунад;
  • навъи дигар (<p> <div> шуд, <Chat> <Profile> шуд) — гиреҳи кӯҳна бо ҳама чизи дохилаш нест мешавад, нав сохта мешавад;
  • дар рӯйхатҳо унсурҳо аз рӯи key мувофиқ карда мешаванд, на аз рӯи тартиб.
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <h1>Ҳисобкунак</h1>
      <p>Пахш шуд: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

Баъд аз клик React Counter-ро боз даъват мекунад, дарахти нав мегирад ва мебинад: div, h1 ва button тағйир наёфтаанд, вале матни p иваз шудааст. Дар DOM як гиреҳи матнӣ иваз мешавад. Агар дар майдони воридкунии саҳифа курсор буд, он гум намешавад: майдонро касе аз нав насохт.

Компонент кай аз нав кашида мешавад

Компонент аз нав даъват мешавад, вақте:

  1. ҳолати худаш тағйир ёфт (set… бо қимати нав даъват шуд);
  2. волидаш аз нав кашида шуд — он гоҳ ҳамаи кӯдакон аз нав кашида мешаванд, ҳатто агар props-ашон тағйир наёфта бошанд;
  3. контекст-е, ки вай мехонад, тағйир ёфт (мавзӯъ дар бораи useContext).

Бовар ҳосил кардан мумкин аст, ки console.log-ро рост ба бадани компонент илова кунед:

function Child({ label }) {
  console.log("render Child", label);
  return <p>{label}</p>;
}

function Parent() {
  const [n, setN] = useState(0);
  console.log("render Parent", n);
  return (
    <div>
      <button onClick={() => setN(n + 1)}>{n}</button>
      <Child label="ман тағйир намеёбам" />
    </div>
  );
}

Ҳар клик ҳам render Parent ва ҳам render Child-ро чоп мекунад. Ин муқаррарӣ ва қариб ҳамеша зуд аст: кашидан — танҳо даъвати функсия, ва DOM барои Child тағйир намеёбад. Чӣ тавр кашиданҳои зиёдатиро гузарондан, вақте ки ин воқеан лозим аст, — дар мавзӯъ дар бораи самаранокӣ.

Аз ин ҷо қоидаи муҳим: компонент бояд функсияи «тоза» бошад. Ҳангоми props ва ҳолати якхела вай JSX-и якхела бармегардонад ва берун аз худ чизеро иваз намекунад: дархост намефиристад, тағйирёбандаҳои глобалиро иваз намекунад, DOM-ро даст намезанад. React метавонад онро ҳар қадар хоҳад даъват кунад. Ҳама чизи «берунӣ» — дар коркардкунандаҳои рӯйдодҳо ва дар useEffect.

Ҳолат — ин акс (snapshot) аст

Дар дохили як кашидан қимати ҳолат тағйир намеёбад. count — доимии оддии ҳамон кашидан аст, ки дар он коркардкунанда сохта шудааст:

function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
    console.log(count);       // ҳанӯз 0!
  }

  return <button onClick={handleClick}>{count}</button>;
}

setCount тағйирёбандаи count-ро иваз намекунад. Вай ба React мегӯяд: «дар кашидани навбатӣ ба count қимати 1-ро деҳ». Қимати нав танҳо вақте пайдо мешавад, ки React Counter-ро боз даъват кунад.

Бастаҳои навсозӣ

Агар дар як коркардкунанда якчанд set… даъват кунед, React компонентро баъд аз ҳар кадом аз нав намекашад: вай онҳоро ба баста ҷамъ мекунад (batching) ва баъд аз коркардкунанда як кашидан мекунад.

function handleClick() {
  setCount(count + 1);   // count = 0 → «1 гузор»
  setCount(count + 1);   // count ҳанӯз 0 → «1 гузор»
  setCount(count + 1);   // «1 гузор»
}
// натиҷа: 1, на 3

Агар қимати нав аз пешина вобаста бошад, функсияи навсозӣ диҳед. React чунин функсияҳоро ба навбат мегузорад ва бо тартиб даъват мекунад, ба ҳар кадом натиҷаи пешинаро дода:

function handleClick() {
  setCount((c) => c + 1);   // 0 → 1
  setCount((c) => c + 1);   // 1 → 2
  setCount((c) => c + 1);   // 2 → 3
}

Қоида: агар қимати навбатӣ аз ҷорӣ ҳисоб шавад — set((кӯҳна) => нав) нависед.

Ҳолатро мустақим иваз кардан мумкин нест

React чӣ тавр мефаҳмад, ки ҳолат тағйир ёфт? Қимати кӯҳна ва навро бо Object.is (қариб ҳамон ===) муқоиса мекунад. Барои объектҳо ва массивҳо ин муқоисаи истинодҳо аст, на мундариҷа:

const [items, setItems] = useState(["a", "b"]);

function addWrong() {
  items.push("c");      // ҳамон массивро иваз кардем
  setItems(items);      // ҳамон истинод → React: «ҳеҷ чиз тағйир наёфт» → кашидан нест
}

function addRight() {
  setItems([...items, "c"]);   // массиви нав → истиноди нав → кашидан
}

Барои ҳамин ҳолатро дар React тағйирнопазир меҳисобанд: ба ҷойи иваз кардан нусхаи нав месозанд.

Амал Массив Объект
Илова [...arr, x] { ...obj, key: value }
Нест кардан arr.filter((x) => x.id !== id) const { key, ...rest } = obj
Иваз кардан arr.map((x) => (x.id === id ? { ...x, done: true } : x)) { ...obj, key: newValue }
Мураттаб кардан [...arr].sort(...) —

Усулҳои push, splice, sort, reverse ва бахшиши obj.key = … аслро иваз мекунанд — барои ҳолат онҳоро истифода намебаранд (ё аввал нусха месозанд).

Дар хотир доред, ки нусха бо ... — рӯякӣ аст: объектҳои дарунӣ низ бояд нусха шаванд ({ ...user, address: { ...user.address, city: "Хуҷанд" } }).

Ҳолат дар куҷо зиндагӣ мекунад: ҷой дар дарахт

Ҳолат на «дар дохили функсия», балки дар React нигоҳ дошта мешавад — ба ҷойи компонент дар дарахт баста шуда. То он даме ки дар ин ҷой компоненти ҳамон навъ истодааст, ҳолат нигоҳ дошта мешавад, ҳатто агар props иваз шуда бошанд:

{selected === "ann" ? <Chat contact={ann} /> : <Chat contact={timur} />}

Барои React ин ҷо ҳамон як <Chat> дар ҳамон ҷой аст — танҳо props-аш иваз шуданд. Сиёҳнависи паёме, ки барои Аня навишта шуда буд, барои Тимур ҳам мемонад. Баъзан ин хато аст.

Барои гуфтани «ин нусхаи дигар аст, аз варақи тоза сар кун» key-ро истифода мебаранд — на танҳо дар рӯйхатҳо:

<Chat key={contact.id} contact={contact} />

key-и нав — React компоненти кӯҳнаро якҷоя бо ҳолат нест мекунад ва навашро месозад. Ин роҳи маъмули тоза кардани форма ё виҷет ҳангоми иваз шудани унсури интихобшуда аст.

Баръакс ҳам дуруст аст: агар компонент аз дарахт нопадид шавад (масалан, тавассути {show && <Panel />}), ҳолати он нест мешавад. Вақте боз пайдо шавад, бо қиматҳои ибтидоӣ сар мекунад.

Реҷаи қатъӣ

Дар лоиҳаҳо барномаро одатан ба <React.StrictMode> мепечонанд. Дар реҷаи коркард вай қасдан компонентҳоро ду бор даъват мекунад ва эффектҳоро ду бор насб мекунад (оғоз → тозакунӣ → оғоз), то компонентҳои нотоза ва эффектҳои бе тозакуниро зудтар ёбад. Агар console.log-ҳои дукаратаро бинед — ин ҳамон аст. Дар сохти тайёр даъватҳои дукарата нестанд.

Хулоса

  • Навсозӣ: оғоз (set…) → кашидан (даъвати компонентҳо) → татбиқ (ислоҳоти ҳадди ақали DOM) → эффектҳо.
  • JSX — объектҳо; React дарахти навро бо кӯҳна муқоиса мекунад ва танҳо фарқро иваз мекунад.
  • Компонент ҳангоми тағйири ҳолати худ, ҳангоми кашидани волид ва ҳангоми тағйири контекст аз нав кашида мешавад. Компонент — функсияи тоза.
  • Ҳолат — акси кашидан; навсозиҳо ба баста ҷамъ мешаванд. Аз қимати кӯҳна — set((old) => ...).
  • Ҳолатро мустақим иваз намекунанд: массивҳо ва объектҳои нав бо ..., map, filter.
  • Ҳолат ба ҷой дар дарахт баста аст; key нусхаи нав месозад ва ҳолатро тоза мекунад.

Плюс се

Осон+10 XP

Компоненти TripleCounter ададро дар <span> ва тугмаи +3-ро нишон медиҳад. Аз рӯи нақша тугма 3 илова мекунад, вале дар код хато ҳаст: баъд аз клик адад танҳо 1 зиёд мешавад.

TripleCounter-ро ислоҳ кунед ва се даъвати setCount-ро нигоҳ доред (ҳамин тавр дидан осонтар аст, ки React навсозиҳоро чӣ тавр коркард мекунад).

0 [+3]  → клик →  3  → клик →  6

Барои ҳал кардани масъалаҳо коннекторро пайваст кун

Коди масъалаҳо дар компютери худат иҷро мешавад — ин аз браузер тезтар ва боэътимодтар аст. Барои ин барномаи ройгони коннектори CodeWithMe лозим аст. Онро як бор пайваст кардан кифоя аст.

Коннекторро дар ин компютер ҷустуҷӯ мекунем…

  1. 1
    Коннекторро барои системаи худ (Windows, macOS ё Linux) зеркашӣ кун.Зеркашии коннекторДар саҳифаи зеркашӣ файлеро интихоб кун, ки дар номаш системаи ту ҳаст, масалан windows-amd64.
  2. 2Онро иҷро кун ва ҷузвдонеро интихоб кун, ки ҳалҳоят дар он ҷо меистанд. Python ва Node.js-ро ӯ худаш ҳангоми зарурат ба он ҷо мегузорад.
  3. 3
    Дар поён рамзи 6-рақамаро ворид кун — он дар равзанаи коннектор навишта шудааст («Рамз барои сайти CodeWithMe»). Агар браузер дар бораи дастрасӣ ба шабакаи маҳаллӣ пурсад — иҷозат деҳ.

Коннектор кушода аст (рамзи манбаъ дар GitHub), танҳо дар компютери ту кор мекунад ва кодро танҳо пас аз ворид кардани рамзи пайвастшавӣ иҷро мекунад.