Holat va hayotiy ketma-ketlik
Bu sahifa React komponentidagi holat(state) va hayotiy ketma-ketlik(lifecycle) tushunchalarini tanishtiradi.Bu yerda batafsil komponentinig API ma’lumotnomasini topa olasiz.
Oldingi bo’limlarning namunalardan biridagi soatga e’tibor bering. Elementlarni chizish bo’limida, biz faqat foydalanuvchi interfeysini(UI) yangilashni bir yo’lini o’rgandik. Biz chizilgan natijani o’zgartirish uchun root.render()
ni chaqiramiz:
const root = ReactDOM.createRoot(document.getElementById('root'));
function tick() {
const element = (
<div>
<h1>Salom, dunyo!</h1>
<h2>Hozir soat {new Date().toLocaleTimeString()}.</h2>
</div>
);
root.render(element);}
setInterval(tick, 1000);
Bu bo’limda, biz qanday qilib Clock
komponentini rostdan ham qayta ishlaydigan va jamlangan qilishni o’rganamiz. Soat komponenti o’zinig taymerini o’rnatadi va har sekundda o’zini yangilaydi.
Biz soat qanday ko’rinishini yig’ishdan boshlaymiz:
const root = ReactDOM.createRoot(document.getElementById('root'));
function Clock(props) {
return (
<div> <h1>Salom, dunyo!</h1> <h2>Hozir soat {props.date.toLocaleTimeString()}.</h2> </div> );
}
function tick() {
root.render(<Clock date={new Date()} />);}
setInterval(tick, 1000);
Ammo, u muhim talabni bajarmadi: bu fakt shuki taymerni o’rnatish va foydalanuvchi interfeysini har soniyada yangilashini Clock
komponenti o’zi amalga oshirish kerak.
Ideal holda biz bu Clock
komponentini bir marta yozishni va o’zi yangilanishini hohlaymiz:
root.render(<Clock />);
Buni amalga oshirish uchun, biz Clock
komponentiga “holat(state)” ni qo’shishimiz kerak.
Holat(State) kiritmalarga(props) o’xshash, lekin u shaxsiy va komponent tomonidan to’liq nazorat qilinadi.
Funksiyani klassga aylantirish
Siz Clock
ga o’xshash funksiyaviy komponentni besh qadamda klass komponentiga aylantira olasiz:
- Bir xil nom bilan
React.Component
dan vorislik oladigan ES6 klassni yarating. - Klassga bitta bo’sh
render()
deb nomlangan metod qo’shing. - Funksiyaning tanasini
render()
metodiga ko’chiring. render()
metodi tanasidagiprops
o’zgaruvchinithis.props
bilan o’zgartiring.- Qolgan bo’sh funksiyani o’chiring.
class Clock extends React.Component {
render() {
return (
<div>
<h1>Salom, dunyo!</h1>
<h2>Hozir soat {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
Clock
hozir funksiya sifatida emas klass sifatida belgilangan.
Har doim yangilanish sodir bo’lganida render
metodi chaqiriladi, lekin agarda biz <Clock />
komponentini bir DOM tuguniga(node) chizsak, Clock
klassining faqat bir modeli(instance) foydalaniladi. Bu bizga qo’shimcha imkoniyatlar jumladan lokal holat va hayotiy ketma-ketlik metodlaridan foydalanishga ruhsat beradi.
Lokal holatni klassga qo’shish
Biz date
ni kiritmalardan(props) holatga(state) uch qadamda ko’chiramiz:
render()
metodidagithis.props.date
nithis.state.date
bilan almashtiring:
class Clock extends React.Component {
render() {
return (
<div>
<h1>Salom, dunyo!</h1>
<h2>Hozir soat {this.state.date.toLocaleTimeString()}.</h2> </div>
);
}
}
- Boshlang’ich
this.state
ni tayinlaydigan klass konstruktorini qo’shing:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()}; }
render() {
return (
<div>
<h1>Salom, dunyo!</h1>
<h2>Hozir soat {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
Qnaday qilib props
ni asosiy konstruktorga o’tkazganimizga etibor bering:
constructor(props) {
super(props); this.state = {date: new Date()};
}
Klass komponentlari har doim asosiy konstruktorni props
bilan chaqirishi kerak.
<Clock />
elementidandate
xususiyatini o’chiring:
root.render(<Clock />);
Keyinchalik taymer kodini komponentning o’ziga qaytaramiz.
Natija shunday ko’rinadi:
class Clock extends React.Component {
constructor(props) { super(props); this.state = {date: new Date()}; }
render() {
return (
<div>
<h1>Salom, dunyo!</h1>
<h2>Hozir soat {this.state.date.toLocaleTimeString()}.</h2> </div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Clock />);
Keyin, biz Clock
komponenti o’zi taymer o’rnatatadigan va har soniyada yangilaydigan qilamiz.
Adding Lifecycle Methods to a Class
Ko’p komponentlarga ega ilovalarda, komponentlar yo’q qilinganda ular tomonidan olingan resurslarni bo’shatish juda muhim.
Biz taymer o’rnatishni hohlaymiz qachonki Clock
komponenti DOMga birinchi marta chizilganda va bu Reactda “mounting” deb ataladi.
Shuningdek, biz taymerni to’xtatishni hohlaymiz qachonki Clock
komponenti tomonidan yaratilgan DOM olib tashlanganda va bu Reactda “unmounting” deb nomlanadi.
Biz komponent o’rnatilganda(mount) va yechilganda(unmount) biror kod bajarish uchun klass komponentida maxsus metodlarni e’lon qilishimiz mumkin:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() { }
componentWillUnmount() { }
render() {
return (
<div>
<h1>Salom, dunyo!</h1>
<h2>Hozir vaqt {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
Bu metodlar hayotiy ketma-ketlik metodlari(“lifecycle methods”) deb ataladi.
componentDidMount()
metodi komponent natijasi DOMga chizilgandan keyin ishlaydi. Bu taymer o’rnatish uchun juda yaxshi joy:
componentDidMount() {
this.timerID = setInterval( () => this.tick(), 1000 ); }
Taymer IDni qanday saqlaganimizga e’tibor bering (this.timerID
).
this.props
React o’zi tomonidan o’rnatilgan va this.state
maxsus ma’noga ega. Agar siz ma’lumot oqimida qatnashmaydigan narsalarni (masalan, taymer identifikatori) saqlashingiz kerak bo’lsa, siz qo’lda klassga qo’shimcha maydonlarni qo’shishingiz mumkin..
Taymerni componentWillUnmount()
hayotiy ketma-ketlik metodida yo’q qilamiz:
componentWillUnmount() {
clearInterval(this.timerID); }
Va nihoyat, biz Clock
komponentini har soniyada ishlatadigan tick()
metodini qo’llaymiz.
Komponent lokal holatiga yangilanishlarni rejalashtirish uchun u this.setState()
dan foydalanadi:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() { this.setState({ date: new Date() }); }
render() {
return (
<div>
<h1>Salom, dunyo!</h1>
<h2>Hozir vaqt {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Clock />);
Endi soat har soniyada ishlaydi.
Keling, nima bo’layotganini va metodlar chaqirilish tartibini tezlik bilan takrorlaylik:
<Clock />
komponentiroot.render()
ga o’tkazilganda, ReactClock
komponentining konstruktorini chaqiradi.Clock
joriy vaqtni ko’rsatishi kerak bo’lganligi sababli, uthis.state
ni joriy vaqtni o’z ichiga olgan ob’ekt bilan boshlaydi. Keyinchalik bu holatni yangilaymiz.- React keyin
Clock
komponentiningrender()
metodini chaqiradi. Shunday qilib, React ekranda nimani ko’rsatish kerakligini bilib oladi. React keyin DOMniClock
komponenti ko’rsatuviga mos keladigan tarzda yangilaydi. - DOMga
Clock
natijasi kiritilganda, ReactcomponentDidMount()
hayotiy ketma-ketlik metodini chaqiradi. Uning ichidaClock
komponenti brauzerdan sekundiga bir martatick()
metodini chaqirish uchun taymerni o’rnatishni so’raydi. - Har soniyada brauzer
tick()
metodini chaqiradi. Uning ichidaClock
komponenti joriy vaqtni o’z ichiga olgan ob’ekt bilansetState()
ni chaqirib, UI yangilanishini rejalashtiradi.setState()
chaqiruvi tufayli React holat o’zgarganini biladi va ekranda nima bo’lishi kerakligini bilish uchunrender()
usulini qayta chaqiradi. Bu safarrender()
usulidagithis.state.date
har xil bo’ladi, shuning uchun renderning qaytargan natijasi yangilangan vaqtni o’z ichiga oladi. React DOMni shunga mos ravishda yangilaydi. - Agar
Clock
komponenti DOMdan o’chirilsa, ReactcomponentWillUnmount()
hayotiy ketma-ketlik metodini chaqiradi, shuning uchun taymer to’xtatiladi.
Holatdan to’g’ri foydalanish
setState()
haqida siz bilishingiz kerak bo’lgan uchta narsa bor.
Holatni to’g’ridan to’g’ri o’zgartirmang
Masalan, bu komponentni qaytadan chizmaydi:
// Wrong
this.state.comment = 'Salom';
Uning o’rniga setState()
dan foydalaning:
// Correct
this.setState({comment: 'Salom'});
siz this.state
ni tayinlay oladigan yagona joy bu konstruktor.
Holat yangilanishlari asinxron bo’lishi mumkin
React ko’p setState()
chaqiruvlarini bittaga tezkorlik uchun guruhlashi mumkin.
Chunki this.props
va this.state
asinxron tarzda yangilanishi mumkin, keyingi holatni hisoblashda ularning qiymatlariga tayanmaslik kerak.
Misol uchun, bu kod hisoblagichni yangilay olmasligi mumkin:
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
Buni tuzatish uchun ob’ektni emas, funktsiyani qabul qiladigan setState()
ning ikkinchi shaklidan foydalaning. Bu funktsiya “oldingi holat”ni birinchi argument sifatida va yangilanishlar bo’lganda “props”ni ikkinchi argument sifatida qabul qiladi:
// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
Biz yuqorida ko’rsatkich funksiyadan foydalandik, lekin u oddiy funktsiyalar bilan ham ishlaydi:
// Correct
this.setState(function(state, props) {
return {
counter: state.counter + props.increment
};
});
Holat yangilanishlari birlashtiriladi
Qachonki siz setState()
ni chaqirganingizda, React obyektni siz taqdim qilgan hozirgi holatga birlashtiradi.
Masalan, sizning statetingiz bir nechta mustaqil o’zgaruvchilarni o’z ichiga olishi mumkin:
constructor(props) {
super(props);
this.state = {
posts: [], comments: [] };
}
Keyin siz mustaqil ravishda alohida setState()
chaqiruvlari bilan yangilay olasiz:
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts });
});
fetchComments().then(response => {
this.setState({
comments: response.comments });
});
}
Birlashish sayoz, shuning uchun this.setState ({comments})
this.state.posts
‘ni buzmasdan qoldiradi, lekin this.state.comments
ni to’liq almashtiradi.
Ma’lumotlar pastga qarab oqadi
Ota(parent) ham, bola(children) komponentlari biror maxsus komponentning holatli(stateful) yoki holatsiz(stateless) ekanligini bila olmaydi va ular maxsus komponentning funktsiya yoki klass sifatida belgilanishi haqida o’ylamaydi.
Shuning uchun holat ko’pincha loakl yoki birlashgan deb nomlanadi. Unga egalik qiladigan va o’rnatgan komponentdan boshqa hech qaysi komponent kira olmaydi.
Komponent o’z holatini bola komponentlariga kiritmalar sifatida o’tkazishni tanlashi mumkin:
<FormattedDate date={this.state.date} />
FormattedDate
komponenti date
ni kiritmalarda oladi va u Clock
holatidan, Clock
kiritmalaridan kelganini yoki qo’lda yozilganligini bilmaydi:
function FormattedDate(props) {
return <h2>Hozir soat {props.date.toLocaleTimeString()}.</h2>;
}
Bu odatda “yuqoridan pastga” yoki “bir tomonlama” ma’lumotlar oqimi deb ataladi. Har qanday holat har doim ma’lum bir komponentga tegishli va bu holatdan olingan har qanday ma’lumotlar yoki foydalanuvchi interfeysi faqat daraxtda(tree) undan “pastda” joylashgan komponentlarga ta’sir qilishi mumkin.
Agar siz komponent daraxtni kiritmalar sharsharasi deb tasavvur qilsangiz, har bir komponentning holati qo’shimcha suv manbaiga o’xshaydi, u o’zboshimchalik bilan birlashadi, lekin u pastga qarab harkatlanadi.
Barcha komponentalar chindan ham izolyatsiya qilinganligini ko’rsatish uchun biz uchta Clock
ni ko’rsatadigan App
komponentini yaratishimiz mumkin:
function App() {
return (
<div>
<Clock /> <Clock /> <Clock /> </div>
);
}
Har bir Clock
o’z taymerini o’rnatadi va mustaqil ravishda yangilanadi.
React ilovalarida komponentning holatli yoki holatsiz ekanligi komponentni amalga oshirish tafsiloti hisoblanadi va bu vaqt o’tishi bilan o’zgarishi mumkin. Holatsiz bo’lgan komponentlarni holatli komponentlar ichida ishlatishingiz mumkin va aksincha.