Funktsional setState - bu React kelajagi

Yangilanish: Men React Rally-da ushbu mavzu bo'yicha keyingi nutq so'zladim. Ushbu xabar "funktsional setState" modeli haqida ko'proq ma'lumotga ega bo'lsa-da, suhbat setState-ni chuqur tushunish haqida ko'proq gap boradi

React JavaScript-da ommabop funktsional dasturlash dasturiga ega. Bu React foydalanadigan komponentlarga asoslangan UI naqshini qabul qilgan ulkan ramkalarga olib keldi. Va endi funktsional isitma umuman veb-rivojlanish ekotizimiga to'kilmoqda.

Ammo React jamoasi bu borada gapirishdan uzoqdir. Ular afsonaviy kutubxonada yashiringan yanada ko'proq funktsional toshlarni kashf etib, chuqur qazishni davom ettirmoqdalar.

Shunday qilib, bugun men sizga sizga React-ga ko'milgan yangi, eng yaxshi saqlanadigan React sirini - Funktsional setState-ni ochib beraman!

OK, men shunchaki bu nomni yaratdim ... va bu mutlaqo yangi yoki sir emas. Yo'q, aniq emas. Qarang, bu React-da yaratilgan naqshdir, uni faqat chuqur qazib olgan ozgina ishlab chiquvchilar bilishadi. Va u hech qachon nomga ega emas edi. Ammo hozir buni amalga oshiradi - Funktsional setState!

Ushbu naqshni tasvirlashda Dan Abramovning so'zlaridan kelib chiqib, Funktsional setState siz qaerda bo'lishni ko'rsatasiz

"Holat o'zgarishini komponentlar sinflaridan alohida e'lon qiling."

Xo'sh?

OK ... siz allaqachon bilgan narsangiz

Reaktsiya - bu komponentlarga asoslangan UI kutubxonasi. Komponent asosan ba'zi xususiyatlarni qabul qiladigan va UI elementini qaytaradigan funktsiya.

funktsiya Foydalanuvchi (rekvizitlar) {
  qaytish (
    
Yoqimli foydalanuvchi
  ); }

Komponentga uning holatini boshqarish va boshqarish kerak bo'lishi mumkin. Bunday holda siz odatda komponentni sinf sifatida yozasiz. Shunda siz uning konstruktor funktsiyasi holatida bo'lasiz:

class User {
  konstruktor () {
    this.state = {
      hisob: 0
    };
  }
  render () {
    qaytish (
      
Ushbu foydalanuvchi {this.state.score}
baholadi     );   } }

Shtatni boshqarish uchun React setState () deb nomlangan maxsus usulni taqdim etadi. Siz uni quyidagicha ishlatasiz:

class User {
  ...
  growthScore () {
    this.setState ({ball: this.state.score + 1});
  }
  ...
}

SetState () qanday ishlashiga e'tibor bering. Siz uni yangilamoqchi bo'lgan holatlarning bir qismini (qismlarini) o'z ichiga olgan ob'ektga o'tkazasiz. Boshqacha qilib aytganda, siz o'tayotgan ob'ekt tarkibiy holatdagi tugmachalarga mos keladigan tugmachalarga ega bo'ladi, so'ngra SetState () ob'ektni holatiga birlashtirish orqali holatni yangilaydi yoki o'rnatadi. Shunday qilib, "davlat".

Ehtimol siz bilmagan narsalar

SetState () qanday ishlaganimizni eslaysizmi? Xo'sh, agar men sizga ob'ektni o'tqazish o'rniga vazifani topshirishingiz mumkinligini aytsam nima bo'ladi?

Ha. setState () funktsiyani ham qabul qiladi. Funktsiya keyingi holatni hisoblash va qaytarish uchun foydalanadigan komponentning oldingi va joriy rekvizitlarini qabul qiladi. Buni quyida ko'ring:

this.setState (funktsiya (holat, rekvizitlar) {
 return {
  ball: davlat.score - 1
 }
});

Shuni esda tutingki, setState () - bu funktsiya, va biz unga boshqa funktsiyani topshiramiz (funktsional dasturlash ... funktsional setState). Bir qarashda, bu juda xunuk bo'lib tuyulishi mumkin, bu juda oddiy qadamlar. Nima uchun hech qachon bunday qilishni xohlaysiz?

Nega funktsiyani setState-ga o'tkazish kerak?

Gap shundaki, shtat yangilanishlari asenkron bo'lishi mumkin.

SetState () chaqirilganda nima bo'lishini o'ylab ko'ring. Reaktsiya dastlab siz setState () ga o'tgan ob'ektni hozirgi holatga birlashtiradi. Keyin u yarashtirishni boshlaydi. U yangi React Element daraxti (sizning ob'ektiv interfeysingiz ob'ekti) yaratadi, yangi daraxtni eski daraxtdan farq qiladi, siz SetState () ga o'tgan ob'ekt asosida nima o'zgarganini aniqlab, so'ngra DOM-ni yangilaydi.

Voy! Juda ko'p ish! Aslida, bu hatto juda soddalashtirilgan xulosa. Ammo Reactga ishoning!

Reaktsiya shunchaki "holat" emas.

Ishlash miqdori tufayli, SetState () raqamini chaqirish sizning holatingizni darhol yangilamasligi mumkin.

Reaktsiya bir necha setState () chaqiruvlarini bitta yangilanishga olib kelishi mumkin.

React bu nimani anglatadi?

Birinchidan, "bir nechta setState () qo'ng'iroqlari" bitta funktsiya ichida setState () ni bir necha bor chaqirishni anglatishi mumkin, masalan:

...
holat = {ball: 0};
// bir nechta setState () qo'ng'iroqlari
o'sishScoreBy3 () {
 this.setState ({ball: this.state.score + 1});
 this.setState ({ball: this.state.score + 1});
 this.setState ({ball: this.state.score + 1});
}
...

Endi reaktsiya paytida, "bir necha setState () qo'ng'iroqlar" ga duch kelganda, "set-state" ni uch marta bajarish o'rniga, React men yuqorida bayon qilgan juda katta ishlardan qochadi va o'ziga o'zi: "Yo'q! Men bu toqqa uch marta chiqmoqchi emasman, har safarda bir necha tilim holatini olib, yangilayman. Yo'q, men konteyner olib, barcha tilimlarni bir joyga yig'ib, yangilashni bir marta amalga oshirgan bo'lardim. ”Va mening do'stlarim!

Shuni esda tutingki, setState () ga o'tishingiz oddiy ob'ektdir. Endi istalgan vaqtda Reaktsiya "bir necha setState () qo'ng'iroqlar" bilan to'qnashadi deb faraz qilaylik, u har bir setState () chaqiruviga yuborilgan barcha ob'ektlarni ajratib olish yo'li bilan birlashtiradi, ularni bitta ob'ektni yaratish uchun birlashtiradi va keyin bu bitta ob'ektni setState qilish uchun ishlatadi ( ).

Birlashtirish JavaScript-da ob'ektlar quyidagicha ko'rinishi mumkin:

const singleObject = Object.assign (
  {},
  objectFromSetState1,
  objectFromSetState2,
  ob'ektFromSetState3
);

Ushbu naqsh ob'ekt tarkibi deb nomlanadi.

JavaScript-da ob'ektlarni "birlashtirish" yoki tuzish usuli ishlaydi: agar uchta ob'ekt bir xil tugmachalarga ega bo'lsa, Object.assign () ga o'tgan ob'ektning kalitining qiymati g'alaba qozonadi. Masalan:

const me = {name: "Adolat"},
      siz = {ismingiz: "Sizning ismingiz"},
      biz = Object.assign ({}, men, siz);
we.name === "Sizning ismingiz"; // rost
console.log (biz); // {ism: "Sizning ismingiz"}

Siz biz bilan birlashtirilgan oxirgi ob'ekti bo'lganingiz uchun, sizning ob'ektingizdagi nomning qiymati - "Sizning ismingiz" - men ob'ekti nomining qiymatini bekor qiladi. Shunday qilib, "sizning ismingiz" uni biz e'tirozimizga olib keladi ... siz g'alaba qozonasiz! :)

Shunday qilib, agar siz biron bir ob'ekt bilan bir necha bor setState () ni chaqirsangiz - har safar ob'ektni o'tkazsangiz - React birlashadi. Yoki boshqacha qilib aytganda, biz uni o'tkazgan bir nechta ob'ektlar ichidan yangi ob'ektni yaratadi. Va agar biron bir ob'ektda bir xil kalit bo'lsa, xuddi shu tugmachaga ega oxirgi ob'ekt kalitining qiymati saqlanadi. To'g'ri?

Bu shuni anglatadiki, yuqoridagi bizningScoreBy3 funktsiyamiz 3 ning o'rniga 1 natijani beradi, chunki React biz setState () deb nomlangan tartibda darhol holatni yangilamadi. Birinchidan, React barcha ob'yektlarni birlashtirdi, natijada: {score: this.state.score + 1}, so'ngra yangi tuzilgan ob'ekt bilan bir marta “sozlash” qilingan. Shunga o'xshash narsa: User.setState ({ball: this.state.score + 1}).

Juda aniq bo'lish uchun, ob'ektni setState () ga o'tkazish bu erda muammo emas. Haqiqiy muammo oldingi holatdan keyingi holatni hisoblash zarur bo'lsa, ob'ektni setState () ga o'tkazish. Shunday qilib, buni qilishni to'xtating. Bu xavfsiz emas!

This.props va this.state asinxron ravishda yangilanishi mumkinligi sababli, keyingi holatni hisoblash uchun ularning qiymatlariga tayanmaslik kerak.

Bu muammoni hal qiluvchi Sophia Shoemakerning qalami. U bilan o'ynang va ushbu qalamda ham yomon, ham yaxshi echimlarga e'tibor bering:

Qutqaruvchiga funktsional to'siq

Agar siz yuqoridagi qalam bilan o'ynashga vaqt sarf qilmagan bo'lsangiz, buni bajarishni maslahat beraman, chunki bu ushbu postning asosiy tushunchasini tushunishga yordam beradi.

Yuqoridagi qalam bilan o'ynab yurganingizda, shubhasiz, funktsional setState bizning muammolarimizni hal qildi. Ammo qanday qilib?

Keling, reaktsiya Oprasi bilan maslahatlashaylik - Dan.

Uning javobiga e'tibor bering. Siz funktsional setState qilganingizda ...

Yangilanishlar navbatga qo'yiladi va keyinchalik ular chaqirilgan tartibda bajariladi.

Shunday qilib, React "bir nechta funktsional setState () qo'ng'iroqlari" bilan to'qnashganda, ob'ektlarni birlashtirish o'rniga, (albatta birlashtirish uchun ob'ektlar yo'q) React vazifalari "ular chaqirilgan tartibda" navbatga qo'yiladi.

Shundan so'ng React har bir funktsiyani "navbat" da chaqirib, oldingi holatni, ya'ni birinchi funktsional setState () chaqiruvidan oldingi holatni (agar u birinchi funktsional setState () bo'lsa) holatni yangilashga o'tadi. hozirda ishlamoqda) yoki holati, avvalgi funktsional setState () qo'ng'irog'ida navbatda turish.

Shunga qaramay, ba'zi kodlarni ko'rish juda yaxshi bo'ladi deb o'ylayman. Bu safar biz barchasini soxtalashtiramiz. Shuni bilingki, bu haqiqiy narsa emas, aksincha React nima qilayotgani haqida sizga ma'lumot berish uchun.

Bundan tashqari, uni oddiyroq qilish uchun biz ES6-dan foydalanamiz. Agar xohlasangiz, har doim ES5 versiyasini yozishingiz mumkin.

Birinchidan, komponentlar sinfini yarataylik. Keyin, uning ichida biz soxta setState () usulini yaratamiz. Bundan tashqari, bizning tarkibiy qismimizda ko'p funktsiyali setState bajaradigan o'sishScoreBy3 () usuli bo'ladi. Va nihoyat, React qilganidek, biz darsni boshlaymiz.

class User {
  holat = {ball: 0};
  // ning qalbaki setState
  setState (holat, qo'ng'iroqni qaytarish) {
    this.state = Object.assign ({}, this.state, state);
    agar (qo'ng'iroqni qaytarib) qayta qo'ng'iroq qilish ();
  }
  // bir nechta funktsional setState qo'ng'irog'i
  o'sishScoreBy3 () {
    this.setState ((holat) => ({ball: state.score + 1})),
    this.setState ((holat) => ({ball: state.score + 1})),
    this.setState ((holat) => ({ball: state.score + 1}))
  }
}
const Justice = yangi foydalanuvchi ();

Shuni esda tutingki, setState ixtiyoriy ikkinchi parametrni - qo'ng'iroqni qaytarish funktsiyasini qabul qiladi. Agar mavjud bo'lsa, React bu holatni yangilaganidan keyin qo'ng'iroq qiladi.

Endi foydalanuvchi афзishScoreBy3 () ni ishga tushirganda, React bir nechta funktsional setState-ni navbatga qo'yadi. Biz bu erda mantiqni soxtalashtira olmaymiz, chunki asosiy diqqat funktsional setState-ni xavfsiz qiladigan narsaga qaratiladi. Ammo siz "navbat" jarayonining natijasi sifatida funktsiyalarning qatori bo'lishi mumkin deb o'ylashingiz mumkin, masalan:

const updateQueue = [
  (holat) => ({ball: state.score + 1}),
  (holat) => ({ball: state.score + 1}),
  (holat) => ({ball: state.score + 1})
];

Va nihoyat, yangilash jarayonini soxtalashtiraylik:

// tartibda rekursiv ravishda holatni yangilang
updateState funktsiyasi (komponent, updateQueue) {
  if (updateQueue.length === 1) {
    return komponent.setState (updateQueue [0] (komponent.state));
  }
return komponent.setState (
    updateQueue [0] (komponent.state),
    () =>
     updateState (tarkibiy qism, updateQueue.slice (1))
  );
}
updateState (Adolat, updateQueue);

To'g'ri, bu unchalik shahvoniy kod emas. Ishonchim komilki, bundan ham yaxshi ish qila olasiz. Ammo bu erda asosiy e'tibor shundan iboratki, har safar React funktsional setState-dan vazifalarni bajarganda, React sizning yangilangan holatingizning yangi nusxasini berib, holatingizni yangilaydi. Bu funktsional setState oldingi holatga asoslanib holatni o'rnatishga imkon beradi.

Bu erda men to'liq kod bilan bir axlat tashladim. Buni tushunish uchun uning atrofidagi tinker (ehtimol uni yanada jozibali qilish uchun).

To'liq tushunish uchun u bilan o'ynang. Qaytib kelganingizda biz funktsional setState-ni chindan ham oltin rangga aylantirganini ko'ramiz.

Eng yaxshi saqlanadigan React siridir

Hozircha, React-da ko'p funktsiyali SetStates-ni nima uchun xavfsiz qilish kerakligini chuqur o'rganib chiqdik. Ammo biz funktsional setState-ning to'liq aniqlanishini bajara olmadik: "Holatni komponentlar sinflaridan alohida e'lon qiling."

Yillar davomida sozlash holati mantig'i, ya'ni biz setState () ga o'tkazadigan funktsiyalar yoki ob'ektlar doimo komponentlar sinflari ichida yashab kelgan. Bu deklarativdan ko'ra muhimroqdir.

Bugun men sizga yangi topilgan xazinani - eng yaxshi saqlangan React sirini taqdim etaman:

Dan Abramovga rahmat!

Bu funktsional setState-ning kuchi. O'zingizning yangilanish mantig'ingizni tarkibiy sinfingizdan tashqarida e'lon qiling. Keyin uni o'zingizning komponent sinfingizda chaqiring.

// sizning komponentangiz sinfidan tashqarida
funktsiya o'sishScore (holat, rekvizitlar) {
  return {ball: state.score + 1}
}
class User {
  ...
// sizning komponent sinfingiz ichida
  handleIncreaseScore () {
    this.setState (growthScore)
  }
  ...
}

Bu deklarativ! Sizning komponentlar sinfingiz endi qanday qilib davlat yangilanishi haqida qayg'urmaydi. U shunchaki o'zi xohlagan yangilanish turini e'lon qiladi.

Buni chuqur anglash uchun, odatda har xil bo'laklarga bo'lingan holda, har xil bo'laklarga ega bo'lgan murakkab tarkibiy qismlar haqida o'ylang. Va ba'zan, har bir yangilash funktsiyasi ko'plab kod satrlarini talab qiladi. Ushbu mantiqning barchasi sizning tarkibiy qismingizda yashaydi. Ammo endi yo'q!

Bundan tashqari, agar siz menga o'xshasangiz, men har bir modulni iloji boricha qisqa saqlashni yaxshi ko'raman, lekin endi sizning modulingiz juda uzoqqa cho'zilganga o'xshaydi. Endi sizning barcha o'zgartirishlar mantig'ingizni boshqa modulga ajratib olish, keyin uni tarkibiy qismingizga import qilish va ishlatish qobiliyatiga egasiz.

"../stateChanges" dan {oshirishScore} ni import qilish;
class User {
  ...
  // sizning komponent sinfingiz ichida
  handleIncreaseScore () {
    this.setState (growthScore)
  }
  ...
}

Endi siz афзоишиScore funktsiyasini boshqa tarkibiy qismda qayta ishlatishingiz mumkin. Faqat uni import qiling.

Funktsional setState bilan yana nima qila olasiz?

Sinovni oson qiling!

Keyingi holatni hisoblash uchun qo'shimcha dalillar ham berishingiz mumkin (bu mening xayolimni puchga chiqardi ... #funfunFunction).

Yana kuting ...

Reaktsiya kelajagi

Yillar davomida reaktsiya guruhi davlat funktsiyalarini eng yaxshi tarzda qanday amalga oshirish bo'yicha tajriba o'tkazmoqda.

Funktsional setState bunga to'g'ri javob bo'lishi mumkin (ehtimol).

Hey, Dan! So'nggi so'zlar?

Agar siz uni shu paytgacha yaratgan bo'lsangiz, ehtimol men kabi hayajonlanasiz. Bugun ushbu funktsional setState bilan tajriba boshlang!

Agar siz biron bir yaxshi ish qildim yoki boshqalar buni ko'rish imkoniyatiga ega bo'lganday his qilsangiz, bizning jamoamizda Reaktsiya haqida ko'proq tushunchani tarqatish uchun quyidagi yashil rangga bosish orqali diqqat bilan bosing.

Agar sizda biron bir javob berilmagan savol bo'lsa yoki siz ba'zi fikrlarga qo'shilmasangiz, bu erda yoki Twitter orqali sharh qoldirishingiz mumkin.

Baxtli kodlash!