در جلسه ی قبل با مبحث lazy loading یا code splitting در کامپوننت های react آشنا شدیم و مزیت های این روش را برایتان توضیح دادیم. نکته ی مهم این بود که چنین قابلیتی در برنامه های بسیار بزرگ کاربرد دارد و در برنامه هایی که کوچک باشند فقط تعداد درخواست های ارسالی به سمت سرور را افزایش می دهد. شاید روش جلسه ی قبل برای شما ناخوشایند بوده باشد. بنابراین می خواهم ویژگی جدیدی به نام React Suspense را به شما معرفی کنم. React Suspense در نسخه ی 16.6 به بالا اضافه شده است بنابراین در نسخه های قبل تر از 16.6 نمی توانید از این قابلیت استفاده کنید.
نکته: اگر نمی دانید از چه نسخه ای از React استفاده می کنید باید فایل package.json را باز کرده و در قسمت dependency ها کتابخانه ی react را پیدا کنید:
نحوه ی تشخیص ورژن react و دیگر پکیج ها از فایل package.json
نکته: در صورتی که نسخه ی کتابخانه ی react شما قدیمی است و می خواهید آن را به روز رسانی کنید باید دستور npm upgrade را در ترمینال خود وارد کنید. این دستور تمامی dependency (وابستگی) های شما را به روز رسانی می کند.
مشاهده این قسمت تنها برای افرادی که اشتراک جادویی داشته باشند، امکانپذیر است. با خرید اشتراک، به همه مطالب جادویی روکسوپلاس دسترسی داشته باشید.
احتمالا برایتان جای سوال است که React.Fragment چیست؟ Fragment ها قابلیت جدیدی هستند که در نسخه ی 16.2 کتابخانه ی React اضافه شده اند و دقیقا همان کار کامپوننت Aux خودمان را برای ما انجام می دهند؛ یک عنصر ریشه ای است که در DOM هیچ چیزی اضافه نمی کند.
همچنین در این پروژه 3 صفحه ی جداگانه داریم:
یک صفحه ی اصلی (Welcome page)
صفحه ی کاربران (User page)
صفحه ی پست ها (Posts page)
سه Route مرتبط با آن ها نیز در فایل App.js قابل مشاهده هستند:
<Route path="/"component={Welcome}exact/>
<Route path="/user"component={User}/>
<Route path="/posts"component={Posts}/>
این صفحات فقط دارای یک تگ <h1> هستند و محتوای دیگری درون خود ندارند اما ما می خواهیم فرض کنیم که محتوای زیادی در این صفحات وجود دارد. بنابراین بهتر است کاری کنیم که صفحات user و posts فقط زمانی بارگذاری و دانلود شوند که کاربر روی آن ها کلیک می کند. در حال حاضر کامپوننت posts به صورت زیر وارد پروژه شده است:
import Posts from'./containers/Posts';
بنابراین همیشه به صورت خودکار دانلود خواهد شد. ما می توانیم این دستور را به شکل زیر بنویسیم:
به زبان ساده یک متغیر به نام Posts (یا هر نام دلخواه دیگری) ساخته ایم و مقدار آن را برابر با فراخوانی متد lazy از کتابخانه ی react قرار داده ایم. این متد یک تابع را به عنوان پارامتر می گیرد که در نهایت یک دستور ()import را retu می کند. این دستور ()import شامل آدرس فایل مورد نظر ما خواهد بود. در حال حاضر نحوه ی نمایش این کامپوننت به شکل زیر است:
<Route path="/posts"component={Posts}/>
این حالت برای react قابل قبول نیست بنابراین باید آن را تغییر دهیم. برای این کار می توان گفت:
<Route path="/posts"render={()=>}/>
در اینجا یک arrow function داریم که قرار است چیزی را retu کند. قبل از آنکه اینجا چیزی بنویسیم باید کامپوننتی به نام Suspense را در پروژه وارد کنیم:
import React,{Component,Suspense}from'react';
حالا در arrow function خود می گوییم:
<Route path="/posts"render={()=>(
<Suspense>
<Posts/>
</Suspense>
)}/>
یعنی باید Suspense را در پروژه بگذاریم و سپس کامپوننت مورد نظر خودمان (همان Posts) را بین تگ های آغازین و پایانی آن قرار بدهیم. البته هنوز یک قدم باقی مانده است:
<Route path="/posts"render={()=>(
<Suspense fallback={<div>Loading...</div>}>
<Posts/>
</Suspense>
)}/>
حالا اگر بارگذاری کدها طول بکشد، react این div را به همراه متن داخلش به کاربر نمایش خواهد داد. البته شما می توانید به جای div از یک spinner یا هر علامت گرافیکی دیگری نیز استفاده کنید.
حالا می توانید مثل جلسه ی قبل به سربرگ network در مرورگر خود (قسمت dev tools) بروید و پس از لود شدن صفحه، روی لینک Posts Page کلیک کنید. به محض انجام این کار مشاهده خواهید کرد که یک فایل جدید در network دانلود می شود که همان کامپوننت Posts ما است.
حالا بگذارید یک حالت دیگر را نیز در نظر بگیریم. تمام کدهای داخل تابع Retu را مثل من کامنت کنید:
مشاهده این قسمت تنها برای افرادی که اشتراک جادویی داشته باشند، امکانپذیر است. با خرید اشتراک، به همه مطالب جادویی روکسوپلاس دسترسی داشته باشید.
واضح است که این متد حالت قبلی State را می گیرد (prevState که قبلا در موردش صحبت کرده بودیم) و آن را برعکس می کند، مثلا اگر true باشد false و اگر false باشد آن را true می کند. حالا این متد را به دکمه ی خودمان متصل می کنیم:
شاید در نگاه اول کد بالا خیلی شلوغ به نظر برسد اما بگذارید برایتان توضیح بدهم تا متوجه آسانی آن بشوید. من می خواهم با کلیک روی دکمه (button) تابع modeHandler اجرا شود تا مقدار state به مقدار true برسد. در خط بعد با یک شرط ساده (از نوع teary operator) چک کرده ایم که اگر state.showPosts برابر true شد کامپوننت Posts درون <suspense> را نمایش دهیم و در غیر این صورت همان کامپوننت <user> نمایش داده می شود. نباید فقط به خاطر اینکه خط ها را شکسته ام و چند پرانتز اضافه کرده ام فکر کنید کد ما پیچیده شده است. همچنین از آنجا که دو عنصر ریشه ای داریم (یک button و دیگری که یا Posts یا User است) باید از React.Fragment استفاده کنیم تا بتوانیم عنصر های کنار هم را در JSX قرار دهیم.
حالا اگر به مرورگر بروید و روی دکمه کلیک کنید، کامپوننت مورد نظر ما دانلود خواهد شد. شما می توانید این پروسه را در سربرگ network مرورگرتان به سادگی تماشا کنید. نکته ی مهمی که باید از این جلسه به یاد داشته باشید این است که قابلیت lazy load کردن کد ها فقط در پروژه های واقعا بزرگ کاربرد دارد (مثل یک وب سایت پیشرفته) و اگر آن را در پروژه های کوچک و ساده پیاده کنید نه تنها وقت شما را گرفته بلکه ممکن است سرعت برنامه تان را کاهش دهند.
هشدار: تمام این مباحث Routing مربوط به front-end است. سرور همیشه درخواست ها را دریافت می کند بنابراین اگر ما آدرسی مثلا شبیه به myapp/first داشته باشیم با خطای 404 مواجه می شویم! چرا؟ به دلیل اینکه سرور چنین آدرسی را نمی شناسد و این آدرس در react تعریف شده است. راه حل این مشکل این است که همیشه (حتی برای خطاهای 404 نیز) فایل HTML را به کاربر برگردانید.
همچنین به عنوان نکته ی آخر توجه داشته باشید که روش بالا برای حل مشکل خطا های 404 کافی است البته در صورتی که برنامه ی شما در صفحه ی اول (آدرس اصلی /) قرار بگیرد. اگر برنامه ی react ای شما قرار است در آدرسی مثل website.com/my-app قرار بگیرد (به جای اینکه در آدرس اصلی website.com قرار بگیرد) باید این آدرس را به عنوان آدرس پایه ی برنامه تعریف کنید. به طور مثال در پروژه ی ما می توان گفت:
render(){
retu(
<BrowserRouter basename="/my-app">
<div className="App">
<Blog/>
</div>
</BrowserRouter>
);
}
بنابراین فقط با اضافه کردن basename مشکل را حل کرده ایم. به امید خدا این فصل هم به اتمام رسید و در فصل بعد قابلیت Routing را به پروژه ی همبرگر ساز خودمان اضافه خواهیم کرد.
مشاهده این قسمت تنها برای افرادی که اشتراک جادویی داشته باشند، امکانپذیر است. با خرید اشتراک، به همه مطالب جادویی روکسوپلاس دسترسی داشته باشید.