بررسی Suspense در ری اکت ! Suspense در React چیست ؟
مدیریت بارگذاری داده ها در فرانت اند همیشه چالش برانگیز بوده! پروسه دریافت اطلاعات از سرور و نمایش اون اطلاعات به کاربر کمی زمانبره و ما باید بتونیم در این حین یک Loading به کاربر نشون بدیم. قابلیت Suspense در ری اکت برای مدیریت حالت Loading و رفع این چالش به ما کمک میکنه.
اگه تا الان Loading رو دستی مدیریت میکردید، خواهشا دیگه اینکارو نکنید 🙂 چون تیم ری اکت تو نسخه 18 این کتابخانه محبوب ویژگی Suspense رو معرفی کرد . با فرانت اندی همراه باشید که میخوایم تخصصی بررسیش کنیم . . .
ویژگی Suspense در ری اکت چیست ؟
Suspense در React به ما کمک میکنه تا کارها/اکشن های Async رو مدیریت کنیم.
در واقع با Suspense میتونیم به کامپوننت بگیم که منتظر باش تا فلان اتفاق بیوفته ( مثلا دیتا از سرور دریافت بشه ) و در این حین یک حالت Loading/منتظر بمانید به کاربر نشون بدیم.
همونطور که میدونید کارهای Async کمی زمانبر هستن ( مثلا دریافت اطلاعات از سرور )
تو این حین که داره اطلاعات از سرور دریافت میشه ( ممکنه چند ثانیه باشه ) ما میتونیم به کمک Suspense به یوزر یک حالت Loading نشون بدیم.
حتی ما میتونیم این حالت Loading رو بصورت همزمان بین چندین کامپوننت به اشتراک بزاریم که باعث بهبود تجربه کاربری ( UX ) میشه.
تا قبل از نسخه 18 که Suspense در React معرفی بشه، ما این کار رو بصورت دستی انجام میدادیم یا از کتابخانه های دیگه برای اینکار استفاده میکردیم. اما از این به بعد میتونیم از این ویژگی قدرتمند React استفاده کنیم.
چطور از Suspense در ری اکت استفاده کنیم ؟
استفاده از Suspense در ری اکت خیلی خیلی ساده و در عین حال بشدت کاربردیه.
در ادامه میخوایم کاربرد Suspense رو در عمل ببینیم.
مدیریت Loading هنگام دریافت اطلاعات از سرور با Suspense
زمانیکه اطلاعات میخواد از سرور دریافت بشه، به دلیل زمانبر بودن این پروسه ما باید یک حالت منتظر بمانید/ Loading به کاربر نشون بدیم. همه ی ما تا الان از روش زیر برای اینکار استفاده میکردیم :
const [users,isLoading] = fetchData('/users')
if (isLoading) {
return // اگه اطلاعات درحال دریافت بود ، کامپوننت لودینگ نمایش داده بشه
}
return // اگه اطلاعات دریافت شد، کامپوننت مورد نظر رو به یوزر نشون بدیم
تو تیکه کد بالا گفتیم که اگه isLoading مقدار True داشت حالت منتظر بمانید رو به کاربر نشون میدیم. و زمانیکه اطلاعات از سرور دریافت شد، کامپوننت اصلی ( در خط 7 ) رو به کاربر نشون میدیم.
تو تیکه کد بالا از Suspense استفاده نکردیم! اما اگه دقیقا همون کار رو با Suspense بخوایم بنویسیم باید بصورت زیر انجامش بدیم:
const users = fetchData('/users')
return (
}> // فالبک جهت مدیریت حالت لودینگ استفاده میشه
)
تو تیکه کد بالا به کمک Suspense تونستیم وضعیت Loading رو مدیریت کنیم.
جدای از اینکه کد ما خیلی مرتب/تمیزتر و خواناتر شده، دیگه از render شرطی بر اساس یک Value یا State استفاده نکردیم. در حقیقت به کمک خود React تونستیم وضعیت Loading رو مدیریت کنیم.
تو تیکه کد اول ما یک isLoading داشتیم که به کمک اون میتونستیم render شرطی انجام بدیم. اما تو تیکه کد دوم دیگه isLoading رو نداریم!
تو مثال بالا React متوجه میشه که باید render محتوای داخل Suspense رو به تاخیر بندازه تا زمانیکه دیتای مورد نظرش از سرور دریافت بشه!
در حقیقت ری اکت متوجه میشه که داریم یک درخواست به سرور میزنیم و میتونه و رندر محتوای Suspense رو تا دریافت کامل اطلاعات از سرور به تاخیر بندازه.
اگه به خط 4 دقت کنیم میبینیم که Suspense از ما یک fallback گرفته. در واقع fallback به ما میگه میخوای در حین دریافت اطلاعات از سرور که ممکنه چندین ثانیه طول بکشه چه چیزی render کنم و به کاربر نشون بدم ؟
ما میتونیم یک متن ساده مثل “منتظر بمانید” بهش بدیم یا یک کامپوننت مثل Loading !
در واقع شما هرچیزی که به fallback بدید، در حین دریافت اطلاعات از سرور به کاربر نمایش داده میشه. به محض اینکه اطلاعات از سرور دریافت شد، محتوای داخل Suspense به کاربر نمایش داده میشه ( یعنی کامپوننت Users )
اما برای اینکه کاربرد اصلی و نقطه قوت Suspense رو متوجه بشیم و ببینیم که تو چه زمینه هایی دقیقا به ما کمک میکنه، باید ببینیم که چه وقت هایی میتونیم از سرور اطلاعات دریافت کنیم!
زمان هایی که در React از سرور اطلاعات دریافت میکنیم ؟
تو ری اکت، در چند زمان میتونیم از سرور اطلاعات خودمون رو دریافت کنیم .
دریافت اطلاعات از سرور بعد رندر ( Fetch-On-Render )
تو این روش زمانیکه کامپوننت ما render شد، درخواست اطلاعات از سرور آغاز میشه. ( پس از mounting )
در این روش پس از رندر کامل کامپوننت، اطلاعات ما از سرور دریافت میشه:
const App = () => {
const [userDetails, setUserDetails] = useState({})
useEffect(() => {
fetchUserDetails().then(setUserDetails)
}, [])
if (!userDetails.id) return در حال دریافت اطلاعات کاربر از سرور
return (
Simple Todo
)
}
روش بالا چندان جالب نیست. چون هر کامپوننت درخواست Async به سرور ارسال میکنه و re-render شدن این کامپوننت باعث re-render کامپوننت های فرزند و درخواست های سرور متعدد میشه!
این اصلا برای Performance اپیکیشن خوب نیست!
دریافت اطلاعات قبل از رندر ( Fetch-Then-Render )
تو این روش قبل از رندر کامپوننت، درخواست دریافت اطلاعات از سرور زده میشه.
تو این روش، میتونیم مشکل تیکه کد قبلی رو حل کنیم :
const fetchDataPromise = fetchUserDetailsAndTodos() // We start fetching here
const App = () => {
const [userDetails, setUserDetails] = useState({})
const [todos, setTodos] = useState([])
useEffect(() => {
fetchDataPromise.then((data) => {
setUserDetails(data.userDetails)
setTodos(data.todos)
})
}, [])
return (
Simple Todo
)
}
تو این روش ما درخواست دریافت اطلاعات از سرور رو به یک فایل جداگانه میبریم. یعنی قبل از اینکه کامپوننت ما ساخته بشه ( mount بشه ) درخواست دریافت اطلاعات از سرور شروع میشه.
تو خط 7 از fetchPromise استفاده کردیم. اتفاقی که اینجا میوفته این هست که ابتدا اطلاعات بصورت کامل از سرور دریافت میشه.
اما تو روش بالا هم یک مشکلی داریم. اینکه هر 2 درخواست بصورت همزمان و موازی باهم شروع میشن و اگر یک درخواست بعد 2 ثانیه تموم بشه ، باید منتظر درخواست بعدی بمونه که مثلا 10 ثانیه زمان میبره. زمانیکه هر 2 پاسخ ها دریافت شدند، بصورت همزمان نمایش داده میشن.
پس این روش هم کارآمد نیست چون کامپوننت اول ثانیه2 قابل نمایش بود، اما تا ثانیه 10 منتظر موند تا نمایش داده بشه!
دریافت اطلاعات از سرور با Suspense در ری اکت
تا اینجای کار باهم 2 روش رو بررسی کردیم و دیدیم که این 2 روش مشکلاتی داشتن.
راه حل ، Suspense در React هست 🙂
درواقع Suspense به ما اجازه میده بلافاصله بعد از شروع درخواست اطلاعات از سرور، رندر کامپوننت خودمون رو آغاز کنیم.
یعی ما رندر کامپوننت و نمایش UI به کاربر رو بصورت متوالی با درخواست اطلاعات از سرور پیش میبریم.
این روش دقیقا مثل روش قبلی ( دریافت اطلاعات قبل از رندر ) هست با این تفاوت که دیگه نیاز نیست تا زمان دریافت پاسخ منتظر بمونیم و کامپوننت رو Render نکنیم.
با Suspense میتونیم بصورت متوالی پروسه Data Fetching و rendering رو جلو ببریم :
const data = fetchData() // this is not a promise (we'll implement something similar)
const App = () => (
<>
Fetching user details...}>
Loading todos...}>
>
)
const UserWelcome = () => {
const userDetails = data.userDetails.read()
// code to render welcome message
}
const Todos = () => {
const todos = data.todos.read()
// code to map and render todos
}
طبق تیکه کد بالا، زمانیکه App برای اولین با ایجاد میشه کامپوننت UserWelcome رندر میشه.
سپس data.userDetails.read صدا زده میشه. اگه دیتا هنوز از سرور دریافت نشده باشه، Suspense باعث میشه که ما یک حالت لودینگ ببینیم.
همین اتفاق برای کامپوننت Todos هم میوفته .
درواقع بزرگترین برتری این روش ( Suspense ) نسبت به روش قبلی ( دریافت اطلاعات قبل از رندر ) این هست که هیچ کامپوننتی منتظر کامپوننت دیگه نمیمونه تا Render بشه.
ویژگی Suspense در ری اکت برای دریافت اطلاعات از سرور ( Data Fetching )
تا مدت ها قبل که ویژگی Suspense نیومده بود، ما مجبور بودیم که از روش های دیگه برای Data Fetching استفاده کنیم که مطابق مثال هایی که بالاتر زدیم دیدیم که کارآمد نیستن و Performance اپیکیشن مارو پایین میارن.
در واقع ویژگی Suspense باعث بهبود تجربه کاربری و Performance اپیکیشن ما میشه. چراکه پروسه مدیریت Loading رو برای ما راحت تر کرده. همچنین با کاهش CLS به بارگذاری سریعتر صفحات ما هم کمک میکنه.
Suspense در React یک الگو هست که ما React Developer ها میتونیم ازش برای مدیریت حالت Loading و Async Action ها استفاده کنیم و دیگه نیازی به مدیریت این موارد بصورت دستی نداریم.
چرا ویژگی Suspense در ری اکت کاربردیه ؟
داستان Suspense به بارگذاری ( Loading ) مربوطه . تو خیلی از موارد ما باید یک اطلاعاتی رو از سرور دریافت کنیم و این پروسه ممکنه چندین ثانیه طول بکشه .
ما باید کاربر رو مطلع کنیم که باید کمی صبر کنی تا اطلاعات نمایش داده بشه.
قبل از نسخه 18 ری اکت که Suspense معرفی نشده بود، ما این کار رو بصورت دستی انجام میدادیم. اما الان این کار رو Suspense برای ما انجام میده.
کاربرد اصلی Suspense در ریکت چیست ؟
اگه بخوایم بطور خلاصه بگیم Suspense چه کاربردی داره، میتونیم به معنی Suspense ( تعلیق ) اشاره کنیم.
در حقیقت Suspense به کامپوننت ما میگه منتظر باش تا فلان اتفاق بیوفته ( مثلا اطلاعات از سرور دریافت بشه ) و در این حین یک حالت Loading به کاربر نمایش میده.
مراقب مشکل Layout Shifts باشید !
زمانیکه محتوا های یک صفحه جابجا میشن و تغییر پیدا میکنن و Layout جابجا میشه، مشکل Layout Shifts رخ میده. این مشکل نه تنها باعث میشه کاربر UX بدی رو تجربه کنه، باعث میشه سئوی صفحه رو هم از دست بدیم.
پس باید مراقب باشیم زمانیکه از Suspense در ریکت استفاده میکنیم، با مشکل Layout Shifts مواجه نشیم.
جمع بندی
تو این مقاله روش های مختلف دریافت اطلاعات از سرور ( Data Fetching ) رو بررسی کردیم و دیدیم که هرکدم چه معایبی دارن و دیدیم که Suspense در ری اکت برای رفع این مشکلات اومده.
در واقع Suspense در React رندر و نمایش یک بخش رو به تاخیر میندازه تا زمانیکه یک اتفاقی بیوفته ( جلوگیری از رندر کامپوننت، تا زمانیکه اطلاعات اون کامپوننت از سرور دریافت بشه )
در حین این تاخیر میتونیم به کاربر یک حالت Loading ( منتظر بمانید ) نمایش بدیم.
اگه به یهینه سازی اپیکیشن های ری اکتی علاقه مند هستین، پیشنهاد میکنم راجب هوک useMemo در ری اکت هم مطالعه کنید.
در واقع Suspense رندر و نمایش یک بخش رو به تاخیر میندازه تا زمانیکه یک اتفاقی بیوفته ( جلوگیری از رندر کامپوننت، تا زمانیکه اطلاعات اون کامپوننت از سرور دریافت بشه )
در حین این تاخیر میتونیم به کاربر یک حالت Loading ( منتظر بمانید ) نمایش بدیم.
Suspense در مواردی که اکشن های Async داریم کاربرد داره. مثل دریافت اطلاعات از سرور یا محاسبات سنگین و . . .
درباره احمد احمدنژاد
من یه برنامه نویس و توسعه دهنده وب هستم که عاشق دنیای صفر و یکم❤️
نوشتههای بیشتر از احمد احمدنژاد
دیدگاهتان را بنویسید