React useEffect: yon ta'sirlar

Shu paytgacha yozgan kodingiz bitta ish qilardi: ma’lumotdan ko’rinish hosil qilish. Lekin ilovaga taymer, sahifa sarlavhasini o’zgartirish yoki serverdan ma’lumot olish kerak bo’lsa, bu ishlar chizish jarayoniga sig’maydi. useEffect shunday ishlar uchun.

Yon ta’sir nima

Farqni ko’ring:

Ko’rinish hosil qilish Yon ta’sir
tasks dan <li> yasash Serverdan tasks olish
Sanoqni ekranga chiqarish document.title ni o’zgartirish
Sinf nomini hisoblash setInterval o’rnatish

Yon ta’sirni komponent tanasiga yozib bo’lmaydi:

// ❌ Shunday qilmang
function Counter() {
  const [count, setCount] = useState(0);

  document.title = `Bosilgan: ${count}`;   // chizish paytida

  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

Komponent funksiyasi ko’p marta va kutilmagan paytlarda chaqirilishi mumkin. U faqat JSX hisoblab qaytarishi kerak — boshqa hech nima qilmasligi kerak.

Birinchi effekt

To’g’ri yozilishi:

import { useState, useEffect } from 'react';

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

  useEffect(() => {
    document.title = `Bosilgan: ${count}`;
  }, [count]);

  return (
    <button type="button" onClick={() => setCount(count + 1)}>
      Bosilgan: {count}
    </button>
  );
}

export default Counter;

Tugmani bosing — brauzer yorlig’idagi yozuv ham o’zgaradi.

useEffect ikki argument oladi:

  1. Funksiya — bajariladigan ish;
  2. Bog’liqliklar massivi — qachon bajarilishini belgilaydi.

Effekt komponent chizilib, DOM yangilangandan keyin ishlaydi. Shuning uchun u chizishni sekinlashtirmaydi.

Bog’liqliklar massivi

Ikkinchi argument effekt qachon qayta ishlashini hal qiladi. Uch variant bor va farqi katta:

// 1. Har chizishda
useEffect(() => {
  console.log("Har safar");
});

// 2. Faqat bir marta — komponent paydo bo'lganda
useEffect(() => {
  console.log("Bir marta");
}, []);

// 3. count o'zgarganda
useEffect(() => {
  console.log("count o'zgardi:", count);
}, [count]);
Ikkinchi argument Qachon ishlaydi
yo’q Har chizishdan keyin
[] Faqat birinchi chizishdan keyin
[count] Birinchi chizishda va count o’zgarganda
[a, b] Birinchi chizishda va a yoki b o’zgarganda

React bog’liqliklarni oldingi qiymatlar bilan solishtiradi. Bittasi ham o’zgargan bo’lsa effekt qayta ishlaydi.

Tozalash funksiyasi

Ba’zi yon ta’sirlar orqasida iz qoldiradi: ishlab turgan taymer, ochiq obuna, qo’shilgan hodisa ishlovchisi. Ular to’xtatilmasa xotira sarflanadi va xatolar chiqadi.

Effekt funksiya qaytarsa, React uni tozalash uchun chaqiradi:

import { useState, useEffect } from 'react';

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const intervalId = setInterval(() => {
      setSeconds((previous) => previous + 1);
    }, 1000);

    // Tozalash funksiyasi
    return () => {
      clearInterval(intervalId);
    };
  }, []);

  return <p>O'tgan vaqt: {seconds} soniya</p>;
}

export default Timer;

Ekranda raqam har soniyada oshadi. Komponent ekrandan ketganda taymer to’xtatiladi.

Ikkinchi holat muhim. [count] bog’liqlikli effekt shunday ketma-ketlik bilan ishlaydi:

count = 0  →  effekt ishladi
count = 1  →  tozalash (eski) → effekt (yangi)
count = 2  →  tozalash (eski) → effekt (yangi)

Ya’ni yangi effekt boshlanishidan oldin eskisi yig’ishtiriladi. Shu tufayli ikkita taymer bir vaqtda ishlab qolmaydi.

Tozalash kerak bo’ladigan holatlar:

// Taymer
useEffect(() => {
  const timeoutId = setTimeout(() => console.log("Vaqt tugadi"), 3000);
  return () => clearTimeout(timeoutId);
}, []);

// Hodisaga obuna
useEffect(() => {
  function handleResize() {
    console.log("Yangi kenglik:", window.innerWidth);
  }

  window.addEventListener("resize", handleResize);
  return () => window.removeEventListener("resize", handleResize);
}, []);

Ikkinchi misolda removeEventListener ga aynan o’sha funksiya berilishi kerak. Shuning uchun handleResize effekt ichida e’lon qilingan.

StrictMode: effekt ikki marta ishlaydi

Endi boshlovchilarni eng ko’p chalkashtiradigan joy. Konsolga yozuv chiqaradigan effekt yozasiz:

useEffect(() => {
  console.log("Effekt ishladi");
}, []);

Bo’sh massiv — demak bir marta ishlashi kerak. Lekin konsolda:

Effekt ishladi
Effekt ishladi

Ikki marta. Kod to’g’ri, xato yo’q.

Tozalash to’g’ri yozilgan bo’lsa ketma-ketlik shunday ko’rinadi:

EFFEKT: obuna ochildi
TOZALASH: obuna yopildi
EFFEKT: obuna ochildi

Oxirida bitta ochiq obuna qoladi — to’g’ri natija.

Bog’liqlikni tushirib qoldirmang

Effekt ichida ishlatilgan har bir holat va props bog’liqliklar massivida bo’lishi kerak:

// ❌ userId o'zgarsa effekt qayta ishlamaydi
useEffect(() => {
  console.log("Foydalanuvchi:", userId);
}, []);

// ✅ To'g'ri
useEffect(() => {
  console.log("Foydalanuvchi:", userId);
}, [userId]);

Birinchi variant “eskirgan qiymat” muammosini beradi: effekt birinchi userId ni yodda saqlab qoladi va yangilanishdan xabarsiz qolaveradi.

useEffect kerak bo’lmagan holatlar

Yangi o’rganayotganlar useEffect ni haddan tashqari ko’p ishlatadi. Ikki keng tarqalgan ortiqcha holat:

1. Boshqa holatdan hisoblanadigan qiymat:

// ❌ Ortiqcha
const [tasks, setTasks] = useState([]);
const [activeCount, setActiveCount] = useState(0);

useEffect(() => {
  setActiveCount(tasks.filter((task) => !task.isDone).length);
}, [tasks]);

// ✅ To'g'ridan-to'g'ri hisoblang
const activeCount = tasks.filter((task) => !task.isDone).length;

Ikkinchi variant qisqaroq, tezroq va nomuvofiqlik ehtimolini yo’qotadi.

2. Foydalanuvchi amaliga javob:

// ❌ Ortiqcha
useEffect(() => {
  if (isSubmitted) {
    sendToServer(form);
  }
}, [isSubmitted]);

// ✅ Ishlovchi ichida
function handleSubmit(e) {
  e.preventDefault();
  sendToServer(form);
}

Qoida: amal foydalanuvchi harakatidan kelib chiqsa — ishlovchida. useEffect esa komponent ekranda paydo bo’lgani yoki ma’lumot o’zgargani uchun bajariladigan ishlar uchun.

Amaliy mashq

  1. Counter yozing va useEffect bilan document.title ni yangilang — brauzer yorlig’idagi yozuv o’zgarishini kuzating.
  2. Konsolga yozuv chiqaradigan useEffect(() => {...}, []) yozing va ikki marta chiqqanini ko’ring.
  3. Unga tozalash funksiyasi qo’shing va konsolda effekt → tozalash → effekt ketma-ketligini kuzating.
  4. Timer komponentini setInterval bilan yozing, tozalashda clearInterval bo’lsin.
  5. clearInterval ni vaqtincha o’chiring va raqam qanday tezlashib ketishini ko’ring — StrictMode ikkita taymer ishga tushirgan. Keyin qaytaring.
  6. Bog’liqliklar massivini butunlay o’chirib ko’ring va npm run lint nima deyishini o’qing.

5-qadam StrictMode ning ma’nosini eng aniq ko’rsatadi: tozalashsiz effekt darrov ikkilanadi va muammo ishlab chiqish paytidayoq ko’rinadi.

Qisqacha xulosa

  • Yon ta’sir — ko’rinish hosil qilishdan tashqari ish: tarmoq, taymer, brauzer API. Komponent tanasiga yozilmaydi.
  • useEffect(fn, deps) effektni chizishdan keyin bajaradi.
  • [] — bir marta, [dep] — bog’liqlik o’zgarganda, massivsiz — har chizishda.
  • Effekt qaytargan funksiya tozalash uchun: komponent ketganda va effekt qayta ishlashidan oldin chaqiriladi.
  • StrictMode da effekt ikki marta ishlaydi — bu xato emas, tozalashni tekshirish uchun ataylab qilingan va faqat ishlab chiqishda bo’ladi.
  • Effekt ichida ishlatilgan har qiymat bog’liqliklar massivida bo’lsin.
  • Boshqa holatdan hisoblanadigan qiymat va foydalanuvchi amaliga javob uchun useEffect kerak emas.

Keyingi darsda serverdan ma’lumot yuklashuseEffect va fetch birgalikda.

Bu dars foydali bo'ldimi?

marta ko'rildi