Reactda ota komponentning holatini bola komponentda o'zgartirish

Oldingi darsda ma'lumotlar bilan holat ota komponentda saqlanar edi, bola komponentlar esa bu ma'lumotlarni prop sifatida olar edilar.

Endi biz mahsulotlarimizni o'zgartirmoqchi bo'lsak. Keling, masalan, mahsulotimizni savatga qo'yadigan tugma yasaylik. Boshlash uchun keling, mahsulotlar massivimizga mahsulot savatda yoki yo'qligini ko'rsatadigan inCart maydonini qo'shamiz:

jsxconst initProds = [
  {id: id(), name: 'product1', cost: 100, inCart: false},
  {id: id(), name: 'product2', cost: 200, inCart: false},
  {id: id(), name: 'product3', cost: 300, inCart: false},
];

Products komponentida mahsulot tegi uchun yana bir inCart atributini qo'shamiz:

jsxfunction Products() {
  const [prods, setProds] = useState(initProds);
  
  const items = prods.map(prod => {
    return <Product
      key   ={prod.id}
      name  ={prod.name}
      cost  ={prod.cost}
      inCart={prod.inCart}
    />;
  });
  
  return <div>
    {items}
  </div>;
}

Keling, bola Product komponentida savat haqida ma'lumot chiqarishni va savatga qo'shish uchun tugma qilaylik:

jsxfunction Product({ id, name, cost, inCart }) {
  return <div>
    name: <span>{name}</span>,
    cost: <span>{cost}</span>,
    <span>{inCart ? 'in cart' : 'not in cart'}</span>
    <button>to cart</button>
  </div>;
}

Qo'shishni amalga oshiramiz

React qoidalariga ko'ra komponent o'z proplarini o'zgartirmasligi kerak. Bu degani bola komponent inCart propini o'zgartirib, o'zini savatga qo'ya olmaydi. Bu noto'g'ri.

To'g'ri usuli - ota komponentdan ma'lum bir mahsulotni savatga qo'shish uchun o'zining prods holatini o'zgartirishni so'rash bo'ladi.

Keling, buni qanday amalga oshirilishini ko'rib chiqaylik.

Ota komponentda addToCart funktsiyasini yasaymiz, u parametr sifatida mahsulotning id sini qabul qiladi va ushbu mahsulot uchun inCart xususiyatini true ga o'zgartiradi:

jsxfunction addToCart(id) {
  setProds(prods.map(prod => {
    if (prod.id === id) {
      prod.inCart = true;
    }
    
    return prod;
  }));
}

Mahsulot tegi uchun biz yaratgan funktsiyani uzatadigan atributni, shuningdek mahsulotning id sini uzatadigan atributni qo'shamiz:

jsxconst items = prods.map(prod => {
  return <Product
    key      ={prod.id}
    id       ={prod.id}
    name     ={prod.name}
    cost     ={prod.cost}
    inCart   ={prod.inCart}
    addToCart={addToCart}
  />;
});

Ko'rib turganingizdek, komponent proplariga nafaqat ma'lum bir ma'lumotlarni, balki funktsiyalarni ham uzatish mumkin.

Products klassining yakuniy kodi quyidagicha bo'ladi:

jsxfunction Products() {
  const [prods, setProds] = useState(initProds);
  
  function addToCart(id) {
    setProds(prods.map(prod => {
      if (prod.id === id) {
        prod.inCart = true;
      }
      
      return prod;
    }));
  }
  
  const items = prods.map(prod => {
    return <Product
      key      ={prod.id}
      id       ={prod.id}
      name     ={prod.name}
      cost     ={prod.cost}
      inCart   ={prod.inCart}
      addToCart={addToCart}
    />;
  });
  
  return <div>
    {items}
  </div>;
}

Endi bola klassida bizga addToCart funktsiyasi mavjud bo'ladi. Keling, ushbu funktsiyani tugma bosilganda chaqiramiz, unga parametr sifatida mahsulotning id sini uzatamiz:

jsxfunction Product({ id, name, cost, inCart, addToCart }) {
  return <div>
    name: <span>{name}</span>,
    cost: <span>{cost}</span>,
    <span>{inCart ? 'in cart' : 'not in cart'}</span>
    <button onClick={() => addToCart(id)}>to cart</button>
  </div>;
}

Ma'lum bo'ladiki, boladagi tugma bosilganda ota funktsiyasi chaqiriladi, u ota holatini o'zgartiradi. Ota holatining o'zgarishi qayta renderlanishni chaqiradi va o'zgartirilgan propni uzatib, bizning mahsulotimizni qayta chizadi.

Задание 1

Oldingi darsdan User komponentini oling. Undagi foydalanuvchini ban qilish uchun tugma paydo bo'lishini taminlang.