به نام خدا
سلام
خب، در ادامه قسمت اول ببینیم دیگه چه چیزای جدیدی در نسخه 6 ریکتروتر داریم؟
در قسمت اول و بخش ششم گفتیم که برای داشتن Nested Route ها نیازی نیست مثل نسخه 5 بیایم روت ها رو داخل خود کامپوننت قرار بدیم، بلکه خود <Route> ها رو تودرتو استفاده میکردیم و با استفاده از کامپوننت Outlet که در نسخه 6 معرفی شده مشخص میکنیم در فلان روت، کامپوننت متناظر اون روت، کجا رندر بشه؟
اما در این نسخه هم میتونیم مثل نسخه قبل، <Route> ها رو داخل خود کامپوننت پدرشون(اونجایی که قراره رندر بشن) قرار بدیم و از Outlet استفاده نکنیم. منتها چندتا نکته وجود داره:
1- Route ها حتما باید داخل <Routes> قرار بگیرن.(در قسمت اول، بخش اول بهش اشاره کردیم)
2- آدرس Route ها نسبیه (لزومی نداره در ابتدای اونها از / استفاده کنیم)
3- باید یک */ به انتهای مسیر(path) Parent Route اضافه کنیم. اگر این کار رو نکنیم، parent route وقتی که URL طولانیتر از مسیر parent route هست و یه اضافاتی دنبالش داره، باهاش جور نمیشه و کامپوننت رندر نمیشه و در نتیجه اون Route ها درونش رندر نمیشن.
مثلا آدرس سایت ما site.com هست، در کد بالا گفتیم کلا هر آدرسی بود، هر چی بعد از /site.com بود، شما بیا کامپوننت Layout رو رندر کن و داخل کامپوننت Layout هم دو تا Route تعریف کردیم(حتما باید داخل Routes باشن) که اگر آدرس site.com/invoices بود، Invoices رندر میشه و اگر site.com/dashboard بود، Dashboard رندر میشه.
اینجا اگر اون */ رو ننویسیم و آدرسم مثلا site.com/abcd باشه، چون آدرس با path ای که به Route دادیم جور نیست، کامپوننت Layout رندر نمیشه و در نتیجه روت های داخل اونهم رندر نمیشن.
در یک کامپوننت میتونیم، چندین <Routes> داشته باشیم که هر کدوم به صورت مستقل اجرا میشن و برحسب URL ،یکی از <Route> های داخلشون رو انتخاب میکنن و رندر میکنن.
این زمانی کاربردیه که بخوایم براساس یک URL ، چندتا کامپوننت مختلف رو در بخش های مختلف رندر کنیم:
اینجا وقتی در / باشیم، هم کامپوننت Home رندر میشه هم MainNav ، چون <Routes> ها به صورت مستقل کار میکنن.
این مفهوم در واقع default child Route حساب میشه. وقتی یه parent route چندتا فرزند داره و URL در مسیر parent route هست، اگر بخوایم یکی از اون child route ها رو به صورت پیشفرض رندر کنیم:
=> یک Route جدید تعریف میکنیم و به جای path از ویژگی index استفاده میکنیم، چون مسیر index route با مسیر پدرش یکیه(وقتی در مسیر parent باشیم، این index route رندر میشه، پس index route ویژگی path نداره.)
در برنامه بالا، وقتی در / باشیم، صفحه خالیه و داخل تگ <main> چیزی نیست و این یجورایی خوب نیست، بهتره به صورت پیشفرض یه چیزی اون وسط رندر بشه، کافیه یک index route اضافه کنیم:
حالا اگر در / باشیم، کامپوننت Activity در Outlet رندر میشه.
اما چطور میتونیم صفحه 404 بسازیم؟ وقتی که URL با هیچ کدوم از مسیرها جور نیست و میخوایم یک صفحه 404 به کاربر نشون بدیم.
=> کافیه یک Route با "*"=path تعریف میکنیم.
این مسیر با هر URL ای match میشه اما کمترین اولویت رو داره، یعنی ریکتروتر تنها زمانی این رو انتخاب میکنه که هیچ Route دیگه ای انتخاب نشده باشه.
وقتی یک URL وارد بشه و با هیچ کدوم از روت ها، همخونی نداشته باشه، کامپوننت NotFoundPage رندر میشه.
=> همانطور که قبلا گفتیم، اینجا ترتیب Route ها مهم نیست. در نسخه قبلی، این صفحه 404 حتما باید به عنوان مسیر آخر قرار داده میشد که اگه کلا هیچ کدوم از بالایی ها انتخاب نشدن، این مسیر انتخاب بشه. اما ریکتروتر 6 باهوش تره و نیازی به این کارا نیست:)
– در بحث Dynamic Routing و URL params همون موارد قبلی و هوک useParams رو داریم:
=> اما در این نسخه امکان استفاده از optional params (همون ?) و Regex در URL params نیست، در نتیجه ساختار های زیر(فعلا) معتبر نیستن:
/users/:id?
/tweets/:id(\d+)
– در بحث state هم در این نسخه، به جای اینکه به ویژگی to ،یک obj بدیم و داخل اون state رو تعیین کنیم، در کامپوننت <Link> ، در کنار to ، یه prop با نام state اضافه شده که اون مقداری که میخوایم منتقل کنیم رو داخل این ویژگی قرار میدیم.
همچنین همونطور که قبلا هم گفتیم، در نسخه قبلی از history.push(obj) استفاده میکردیم، اما اینجا از navigate استفاده میکنیم و به عنوان آرگومان دوم یک optionObj داریم که ویژگی state داره:
حالا در روت مقصد چطور به این state ای که ارسال کردیم دسترسی داشته باشیم؟ خیلی ساده با استفاده از هوک useLocation :
نکته: مقدار state که میفرستیم، serialize میشه، پس نمیتونیم داده های non-serializable مثل تابع، promise و... رو بفرستیم، در این صورت مقدار state که دریافت میشه null خواهد بود.
خب تقریبا همه موارد رو بررسی کردیم، تغییرات این نسخه به صورت خلاصه میشه موارد زیر:
- حذف ویژگی exact
- حذف withRouter
- حذف Switch و اضافه شدن Routes
- حذف component & render props و اضافه شدن element به جای اونها
- حذف history و اضافه شدن هوک useNavigate
- حذف Redirect و اضافه شدن Navigate
- عدم امکان استفاده از regex در url params و همینطور optional params
- باهوش تر شدن ریکتروتر در انتخاب مسیر مناسب و عدم نیاز به رعایت ترتیب خاصی در چیدن Route ها
- اضافه شدن Outlet و امکان استفاده از Nested Route ها
- حذف activeClassName و activeStyle در <NavLink>
هوکها و موارد دیگهای هم اضافه شدن که میتونید اونها رو در مستندات خود ریکتروتر بررسی کنید.
سعی کردم در این دو پست، تغییرات و ویژگی های نسخه جدید React Router رو بررسی کنم، امیدوارم استفاده کرده باشید و مفید بوده باشه.
ممنون که وقت گذاشتید و مطالعه کردید.