React Suspense یکی از ویژگیهایی میباشد که در بین توسعهدهندگان React بسیار محبوب شده است. در این مقاله قصد داریم تا با مفهوم React Suspense بیشتر آشنا شویم و ویژگیها، موارد استفاده و تغییراتی که استفاده از آن بر روی وب اپلیکیشنها اعمال میکند را باهم بررسی نماییم.
React suspense یکی از ویژگیهایی است که در نسخه ۱۶٫۶ React معرفی شده است. کامپوننتها هنگامی که از این ویژگی استفاده میکنند، ممکن است در حالی که منتظر پایان یافتن یک فرآیند asynchronous، مانند بازیابی دادهها، هستند عمل رندر کردن را متوقف نمایند.
React suspense برای ساختن آسانتر برنامههایی برای توسعهدهندگان ایجاد شد که نشانههای loading بهبود یافته و تجربه کاربری منسجمتری دارند. این ویژگی امکان متوقف کردن رندر درخت کامپوننت را تا زمانی که معیارهای خاصی برآورده شود، ممکن میسازد، که این اتفاق کار کردن توسعهدهندگان با دادههای asynchronous را آسانتر میکند.
مدیریت loading stateها در React قبل از React Suspense کمی پیچیدهتر بود. توسعهدهندگان مجبور بودند مکانیسم loading را با استفاده از فریمورکهای third-party مانند Redux یا Mobx، رندر شرطی یا مدیریت state پیادهسازی کنند. این کار اغلب منجر به ایجاد کدهای پیچیده و مستعد خطا میشد.
این مشکل توسط React Suspense حل شد که روش یکپارچهتری را برای مدیریت اقدامات asynchronous و loading stateها ارائه میدهد.
در این بخش قصد داریم تا در مورد برخی از مفاهیم و ویژگیها صحبت کنیم تا به درک درستی از React Suspense و نحوه عملکرد آن برسیم.
یک المنت ضروری React Suspense، کامپوننت Suspense
است. کامپوننت Suspense
این امکان را به ما میدهد تا نحوه مدیریت محتوای fallback را در حالی که اقدامات asynchronous در حال تعلیق هستند، بیان کنیم و هر بخشی از درخت کامپوننت خود را کپسوله نماییم.
<Suspense fallback={<LeoFallback />}> <LeoComponent /> </Suspense>
در مثالی که داریم، اگر LeoComponent
آماده نباشد React به جای آن، کامپوننت LeoFallback
را نمایش میدهد.
React.lazy()
یا lazy()
React دارای یک مکانیسم import داینامیک به نام lazy()
است که به ما این امکان را میدهد تا کامپوننتها را به شیوه lazy لود کنیم.
اساساً، lazy loading به این نیاز اشاره دارد که یک کامپوننت یا بخشی از کد فقط در صورت نیاز بارگذاری شود. این قابلیت، اغلب همراه با React Suspense استفاده میشود تا کامپوننتها را فقط در صورت نیاز بارگذاری کند و به این ترتیب سرعت برنامهای که داریم را افزایش دهد.
این کار برای به حداقل رساندن سرعت لود شدن برنامه و کاهش اندازه اولیه باندل بسیار مفید میباشد.
اکنون قصد داریم تا lazy()
را عمیقتر بررسی کرده و نحوه عملکرد آن را یاد بگیریم.
lazy()
برای استفاده از lazy()
، باید مراحل زیر را دنبال کنیم:
ابتدا کامپوننتهای Suspense
و همچنین هر کامپوننتی که میخواهیم با lazy بارگذاری کنیم را از React وارد میکنیم.
import { Suspense } from 'react';
سپس از lazy()
برای تعریف import داینامیک استفاده مینماییم. در کامپوننتی که میخواهیم آن را به آرامی لود کنیم، lazy()
یک تابع را به عنوان آرگومان میپذیرد و عبارت import داینامیک را تولید میکند.
const LeoComponent = lazy(() => import('./LeoComponent'));
در این مثال، LeoComponent
در صورت نیاز به شکل lazy لود میشود. عبارت import()
دینامیک هم مسیر کامپوننتی را که میخواهیم import کنیم، مشخص مینماید.
در مرحله بعد، المنتی را که میخواهیم به شکل lazy لود کنید، در یک المنت Suspense قرار میدهیم. میتوانیم یک کامپوننت backup تعیین کنیم تا زمانی که کامپوننت لود شده به شکل lazy با استفاده از کامپوننت Suspense
بازیابی میشود، نمایش داده شود.
function App() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <LeoComponent /> </Suspense> </div> ); }
در مثال بالا، در حالی که LeoComponent
در حال fetch شدن میباشد، کامپوننت fallback نمایش داده میشود که نشان میدهد محتوا در حال لود شدن است.
React.lazy()
lazy()
این است که تقسیم کد را امکانپذیر میکند. فرآیند تقسیم کد شامل تقسیم کد برنامه به بستههای کوچکتر و درخواستی است. این کار اندازه اولیه بسته نرم افزاری را به حداقل میرساند و زمان لود شدن برنامه را سریعتر میکند.با استفاده از lazy()
، میتوانیم تقسیم کد و بارگذاری lazy کامپوننتها را در برنامههای React خود انجام دهیم. این ویژگی ابزار مفیدی برای سادهسازی کارایی و کاهش زمان لود شدن اپلیکیشنها میباشد، و با لود کردن کامپوننتها تنها در صورت نیاز، تجربه کاربری را بهبود میبخشد.
کامپوننتهای React که به عنوان Error Boundaryها شناخته میشوند، توانایی شناسایی و مدیریت خطاهای داخل زیردرخت خود را دارند. از آنجا که آنها میتوانند هر مشکلی که در حین انتظار برای دادههای asynchronous ایجاد میشود را مدیریت کنند، برای مقابله با suspense ضروری هستند.
class ErrorBoundary extends React.Component { componentDidCatch(error, info) { // Handle the error } render() { return this.props.children; } }
React Suspense به عنوان بخشی از Concurrent Mode معرفی شد که یک مجموعه آزمایشی از ویژگیهای React میباشد. Rendering همزمان پس از آن معرفی شده است.
Rendering همزمان اجرای چندین کار را به صورت همزمان امکانپذیر میسازد و پاسخگویی و کارایی برنامههای React را بهبود میبخشد. این مورد یکی از کامپوننتهای Concurrent Mode است، مجموعهای از ویژگیهای آزمون و خطا که برای غلبه بر برخی از معایب React rendering معمولی طراحی شدهاند.
هدف اصلی rendering همزمان این است که از روان و پاسخگو بودن رابط کاربری حتی زمانی که React در حال مدیریت renderingهای پیچیده یا سایر عملیات asynchronous میباشد، اطمینان حاصل نماید.
هنگام استفاده از React Suspense با عملیات asynchronous، مراحل زیر انجام میشود:
lazy()
import یا دریافت داده)، React تا زمانی که دادهها آماده شوند fallback UI موجود را به کاربران نمایش میدهد.توجه به این نکته لازم است که تمامی این مراحل به صورت خودکار انجام میشوند. از این رو، مدیریت اقدامات asynchronous برای توسعهدهندگان آسانتر است زیرا نیاز به کدنویسی منطقهای پیچیده وجود ندارد.
React Suspense یک ابزار منعطف است که ممکن است در سناریوهای مختلفی مورد استفاده قرار بگیرد که شامل موارد زیر میباشد:
ویژگی دریافت داده React Suspense مدیریت لود شدن asynchronous داده در برنامههای React را آسانتر میکند. React Suspense به ما این امکان را میدهد که rendering را تا زمانی که دادهها در دسترس قرار بگیرند به تعویق بیندازیم و با ارائه محتوای fallback یا نشانههایی مبنی بر بارگذاری دادهها، تجربه کاربری را بهبود ببخشیم.
برای درک بهتر این موضوع، مثالی را با استفاده از یک API ساختگی برای نشان دادن نحوه بازیابی دادهها با استفاده از React Suspense بررسی میکنیم.
در ادامه روش استفاده از React Suspense برای مدیریت لود شدن دادهها، با فرض اینکه از فریمورکهایی مانند React Query یا Relay برای دریافت دادهها استفاده میکنیم را داریم:
ابتدا باید یک Error Boundary و یک کامپوننت React Suspense تنظیم کنیم تا اگر حین بازیابی دادهها با هر گونه خطایی مواجه شدیم بتوانیم آن را ثبت نماییم. در مثال زیر نحوه ایجاد یک کامپوننت ErrorBoundary
سفارشی در react برای دریافت داده را داریم:
import React from 'react'; class ErrorBoundary extends React.Component { producer(props) { unique(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } render() { if (this.state.hasError) { return <div>Error: Something is wrong!</div>; } return this.props.children; } } export default ErrorBoundary;
اگر از React Query برای بازیابی دادهها استفاده کنیم، میتوانیم کامپوننتی بسازیم که از useQuery
برای بازیابی دادهها استفاده میکند و آن را در Suspense
قرار میدهد:
import React from 'react'; import { useQuery } from 'react-query'; import ErrorBoundary from './ErrorBoundary'; // Define your data-fetching function async function fetchData() { const response = await fetch('https://api.example.com/data'); if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); } function DataFetching() { const { data, isLoading, isError } = useQuery('data', fetchData); if (isLoading) { throw new Promise((resolve) => setTimeout(resolve, 2000)); // Simulate loading delay } if (isError) { throw new Error('Error while fetching data'); } return ( <div> <h1>Fetching data with React Suspense</h1> <p>{data}</p> </div> ); } function App() { return ( <div> <h1>Leo's App</h1> <ErrorBoundary> <React.Suspense fallback={<div>Loading...</div>}> <DataFetchingComponent /> </React.Suspense> </ErrorBoundary> </div> ); } export default App;
در این مثال، ما دادهها را با استفاده از هوک useQuery
دریافت میکنیم. برای نمایش نشانگر loading، یک Promise جدیدی را میسازیم تا در صورتی که لود شدن دادهها با تاخیر همراه بود، بتوانیم آن تاخیر را اعمال نماییم (isLoading
دارای مقدار true
است). همچنین یک error نیز ایجاد میکنیم تا در صورت وجود مشکل، error boundary بتواند آن را مدیریت کند.
میتوانیم با قرار دادن کامپوننت DataFetching
در Suspense
، یک کامپوننت پشتیبان برای نمایش به کاربران در حین لود شدن دادهها تهیه نماییم. در این مثال یک پیام ساده Loading...
را داریم.
همچنین باید اطمینان حاصل کنیم که مدیریت خطا، نشانگر loading و تابع دریافت داده همگی بر اساس نیازهای data-fetching منحصربهفرد ما شخصیسازی شده باشند.
این مثال نشان میدهد که چگونه React Suspense مدیریت state و دریافت دادهها را آسانتر میکند و منجر به ایجاد یک پایگاه کد سازمانیافتهتر و قابل درکتر میشود.
لود کردن کامپوننتهای برنامه فقط در صورت نیاز، میتواند اندازه بسته اولیه برنامه را کاهش دهد و لود شدن برنامه React را سرعت ببخشد.
میتوانیم از React.lazy()
همراه با React Suspense
استفاده کنیم تا به راحتی lazy loading را در برنامه خود قرار دهیم.
در اینجا مراحل اجرای lazy loading با React suspense را بررسی میکنیم:
ابتدا React Suspense را از React وارد میکنیم:
import { Suspense } from 'react';
در مرحله بعد، یک کامپوننت lazy loaded در برنامه React خود میسازیم. برای ساخت کامپوننتی که به کندی لود میشود، از متد React.lazy()
استفاده میکنیم. برای import کردن کامپوننت به صورت داینامیک، از یک arrow function استفاده میکنیم:
const LennyComponent = lazy(() => import('./LennyComponent'));
سپس کامپوننت خود و قسمتی که میخواهیم به کندی لود شود را درون Suspense
قرار میدهیم. در حالی که کامپوننت lazy در حال لود شدن است، میتوانیم یک نشانگر loading یا کامپوننت fallback را برای نمایش به کاربران تعیین نماییم.
function App() { return ( <div> <h1>Leo's App</h1> <Suspense fallback={<div>Loading...</div>}> <LennyComponent /> </Suspense> </div> ); }
این کامپوننت را میتوانیم مانند هر کامپوننت دیگری در برنامه React خود مورد استفاده قرار دهیم.
function LennyComponent() { return <div>This component is lazily loaded.</div>; }
برای تکمیل ساخت برنامه، باید از یک سرور توسعه و ابزاری مانند Webpack برای ساختن و سرویسدهی برنامه خود استفاده کنیم تا اطمینان حاصل نماییم که تقسیم کد به درستی و طبق برنامه عمل میکند. کد ما به طور خودکار با استفاده از Webpack برای lazy loading به قطعات کوچکتر تقسیم میشود.
این راهاندازی، اندازه اولیه باندل را به حداقل میرساند و با لود کردن LazyComponent
در صورت نیاز، سرعت لود شدن برنامه React ما را افزایش میدهد. در حالی که کامپوننت در حال بازیابی است، کاربران نشانگر loading را مشاهده خواهند کرد (در این مثال، Loading...
میباشد). این کامپوننت لود شده و به راحتی در برنامه رندر میشود.
React Suspense را میتوانیم برای اطمینان از تجربه کاربری روان با نشان دادن نشانگرهای loading یا محتوای fallback در حین لود شدن دادهها مورد استفاده قرار دهیم. این امر زمان loading درک شده را برای افرادی که از برنامه React ما استفاده میکنند کاهش میدهد.
برای مثال، فرض کنید یک کامپوننتی داریم که دادهها را از یک API با استفاده از fetch
دریافت میکند و ما قصد داریم در حین دریافت دادهها، اسپینر loading را نمایش دهیم. در ادامه یک مثال با استفاده از React Suspense را داریم.
import React, { Suspense } from 'react'; // A component that fetches data const fetchApiData = () => { return new Promise((resolve) => { setTimeout(() => { resolve('Data loaded!'); }, ۲۰۰۰); // Simulating a 2-second delay for data fetching }); }; // A component that uses Suspense to handle asynchronous data fetching const DataComponent = () => { const apidata = fetchApiData(); // This can be any async function, like an API call return <div>{apiData}</div>; }; // Wrapping the component with Suspense const App = () => { return ( <Suspense fallback={<LoadingSpinner />}> <DataComponent /> </Suspense> ); }; // A simple loading spinner component const LoadingSpinner = () => { return <div>Loading...</div>; };
در کد بالا:
متد fetchApiData
توسط کامپوننت DataComponent
برای دریافت داده استفاده میشود. باید به این نکته توجه داشته باشیم که اگرچه fetchApiData
یک تابع ساده است که یک promise را return میکند، اما ممکن است در واقع یک فراخوانی API در یک اپلیکیشن واقعی باشد.
کامپوننت Suspense
که به یگ آرگومان fallback نیاز دارد، کامپوننت App را کپسوله میکند. یکی از کامپوننتهایی که در حین اجرای عملیات asynchronous نمایش داده میشود، prop fallback است. در این مثال این کامپوننت LoadingSpinner
میباشد.
React Suspense هنگام رندر شدن DataComponent
از دریافت خودکار دادههای asynchronous مراقبت میکند. اگر دادهها هنوز در دسترس نباشند، کامپوننت LoadingSpinner
رندر میشود. پس از بازیابی اطلاعات، رابط کاربری بهروزرسانی میگردد.
این متد نیاز به مدیریت دستی state loading را از بین میبرد و یک تجربه کاربری یکپارچهتری را ایجاد میکند.
React Suspense یک روش سادهتر و یکپارچهتری را برای مدیریت اقدامات asynchronous و loading stateها ارائه میدهد. میتوانیم از آن برای طراحی برنامههایی استفاده کنیم که زمان loading سریعتر، دریافت دادههای کارآمدتر و تجربههای کاربری بهتر را با استفاده از Suspense
، React.lazy()
و error boundaryها ارائه میدهند.
۵۰ درصد تخفیف ویژه پاییز فرانت کست تا پایان هفته
کد تخفیف: atm