بررسی 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 به کاربر نشون بدیم. همه ی ما تا الان از روش زیر برای اینکار استفاده میکردیم : چطور از Suspense در ری اکت استفاده کنیم ؟استفاده از Suspense در ری اکت خیلی خیلی ساده و در عین حال بشدت کاربردیه.در ادامه میخوایم کاربرد Suspense رو در عمل ببینیم.مدیریت Loading هنگام دریافت اطلاعات از سرور با Suspenseزمانیکه اطلاعات میخواد از سرور دریافت بشه، به دلیل زمانبر بودن این پروسه ما باید یک حالت منتظر بمانید/ Loading به کاربر نشون بدیم. همه ی ما تا الان از روش زیر برای اینکار استفاده میکردیم :const [users,isLoading] = fetchData('/users')if (isLoading) { return <Loading /> // اگه اطلاعات درحال دریافت بود ، کامپوننت لودینگ نمایش داده بشه}return <Users data={users} /> // اگه اطلاعات دریافت شد، کامپوننت مورد نظر رو به یوزر نشون بدیمتو تیکه کد بالا گفتیم که اگه isLoading مقدار True داشت حالت منتظر بمانید رو به کاربر نشون میدیم. و زمانیکه اطلاعات از سرور دریافت شد، کامپوننت اصلی ( در خط 7 ) رو به کاربر نشون میدیم.تو تیکه کد بالا از Suspense استفاده نکردیم! اما اگه دقیقا همون کار رو با Suspense بخوایم بنویسیم باید بصورت زیر انجامش بدیم:const users = fetchData('/users') return ( <Suspense fallback={<Spinner />}> // فالبک جهت مدیریت حالت لودینگ استفاده میشه <Users data={users} /> </Suspense> )تو تیکه کد بالا به کمک 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 <p>در حال دریافت اطلاعات کاربر از سرور</p> return ( <div className=&quotapp&quot> <h2>Simple Todo</h2> <UserWelcome user={userDetails} /> <Todos /> </div> ) }روش بالا چندان جالب نیست. چون هر کامپوننت درخواست 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 ( <div className=&quotapp&quot> <h2>Simple Todo</h2> <UserWelcome user={userDetails} /> <Todos todos={todos} /> </div> ) }تو این روش ما درخواست دریافت اطلاعات از سرور رو به یک فایل جداگانه میبریم. یعنی قبل از اینکه کامپوننت ما ساخته بشه ( 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 = () => ( <> <Suspense fallback={<p>Fetching user details...</p>}> <UserWelcome /> </Suspense> <Suspense fallback={<p>Loading todos...</p>}> <Todos /> </Suspense> </> ) 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 اطلاعات رو از سرور دریافت کنیم!؟لطفا برای مطالعه ادامه مقاله روی لینک زیر کلیک کنید : ‫Suspense در ری اکت