setState بهروزرسانی فوری وضعیت را انجام نمیدهد
در زمان استفاده از setState، وضعیت بلافاصله تغییر نمی کند و باید تا رندر مجدد صبر کرد. برای مثال در کرد زیر بعد از تغییر boardAddModalShow، هنوز مقدار قبلی نمایش داده میشود.
class BoardAdd extends React.Component {
constructor(props) {
super(props);
this.state = {
boardAddModalShow: false
};
this.openAddBoardModal = this.openAddBoardModal.bind(this);
}
openAddBoardModal() {
this.setState({ boardAddModalShow: true }); // set boardAddModalShow to true
/* After setting a new state it still returns a false value */
console.log(this.state.boardAddModalShow);
}
render() {
return (
<Col lg={3}>
<a href="javascript:;"
className={style.boardItemAdd}
onClick={this.openAddBoardModal}>
<div className={[style.boardItemContainer,
style.boardItemGray].join(' ')}>
Create New Board
</div>
</a>
</Col>
);
}
}
این به این دلیل است متد setState در ریاکت ناهمگام (asynchronous) است. به این معنی که نمیتوانید آن را در یک خط فراخوانی کنید و انتظار داشته باشید که وضعیت در خط بعدی تغییر کرده باشد. setState یک انتقال وضعیت در انتظار ایجاد میکند و نه یک تغییر فوری در this.state. دسترسی به this.state بعد از فراخوانی این متد، میتواند مقدار قبلی را برگرداند. این رفتار به دلیل بهینهسازی عملکرد و جلوگیری از مسدود شدن مرورگر است؛ زیرا تغییر وضعیت و رندر مجدد میتواند عملیاتی پرهزینه باشد. برای دسترسی به مقدار بهروزشده وضعیت، باید از تابع بازگشتی (callback) setState استفاده کنید. این تابع پس از تکمیل بهروزرسانی وضعیت فراخوانی میشود.
به عنوان مثال:
openAddBoardModal() {
this.setState({ boardAddModalShow: true }, () => {
// در اینجا میتوانید از مقدار بهروزشده state استفاده کنید.
// به جای console.log میتوانید هر عمل دیگری را انجام دهید.
});
}
در مثال بالا، تابع console.log در داخل تابع بازگشتی قرار میگیرد و بنابراین پس از بهروزرسانی state اجرا میشود و مقدار صحیح را نمایش میدهد. اگر از ابزارهای لینت مانند ESLint استفاده میکنید که استفاده از console.log را ممنوع میکند، میتوانید به جای آن یک تابع دیگر را در callback قرار دهید که از مقدار بهروزشده state استفاده میکند. این تابع میتواند هر عملیاتی را که بر اساس state بهروزشده مورد نیاز است انجام دهد.
برای برنامههای کاربردی مبتنی بر Hook، از useEffect استفاده کنید. useEffect به شما امکان میدهد تا در واکنش به تغییرات در state، کدهای جانبی اجرا کنید. مهم است که متغیرهایی که useEffect به آنها وابستگی دارد را در آرایه دوم آرگومان آن لیست کنید تا useEffect تنها زمانی اجرا شود که مقادیر این متغیرها تغییر کند.
بهطور خلاصه، برای اطمینان از اینکه از مقدار بهروزشده state استفاده میکنید، همیشه از تابع بازگشتی setState استفاده کنید یا در صورت استفاده از Hookها، از useEffect با آرایه وابستگی مناسب بهره بگیرید.