Три слова про паралельний роутинг в Next.JS
💡Що таке паралельні роути максимально простими словами?
Паралельні роуту в Next.JS це, всього-на-всього, можливість відобразити декілька компонентів на одній сторінці, але так, наче це повноцінні сторінки.
👉А вже з цього випливає, що до цих компонентів застосовуються звичні нам правила сторінок в Next.JS:
- Вони серверні за замовчанням — відповідно ми можемо зробити асинхронний запит прямо в середині компонента та не створювати в ньому стейт
- Підтримують loading.tsx — вам достатньо додати цей файл з дефолтним експортом, і цей компонент буде відображений під час виконання асинхронного запиту. (не треба оброблювати стан loading)
- Підтримують error.tsx — додаємо файл з дефолтним експортом і не мучаємося з обробкою помилок
- Прив’язані до URL, відповідно керувати їх появою та зникненням можна просто змінюючи URL (наприклад по кліку на Link). При цьому інші під сторінки залишаються на місті, не стрибають та не рендеряться наново.
- А ще це чудо техніки підтримує паралельне та навіть умовне завантаження!
😍І все це у формі звичних нам React компонентів. Такий підхід може зменшити обсяг вашої роботи та ще й спростити код, оскільки нам не доведеться писати всю цю магію самостійно. Скажіть просто і круто?
😅На жаль, лише в теорії. На практиці не все так просто і чудово як пише документація. Є баги, є проблеми, є взагалі чорті що, якщо хоч трохи відхилятися від базового прикладу. До речі, іноді рестарт сервера магічним чином допомагає зекономити пів години, майте це на увазі.
🔨 Як це виглядає на практиці?
Тепер подивимось на них з практичної сторони: створимо два незалежних віджети які будуть вантажитися паралельно з власною обробкою помилок та стану завантаження:
- Створіть новий Next.JS проєкт за допомогою create-next-app@latest parallel-demo
- В теці app створіть теки @widget1 та @widget2. Назви можуть бути довільними, але обов’язково починатися з @.
Знак @ пояснює Next-у що там будуть паралельні роути. Важливо, що назва такої теки не бере участі в роутингу. Так шлях app/@widget/login/page.tsx буде розрахований як app/login
- В кожній з тек створіть файл page.tsx з дефолтним експортом. В компоненті напишіть щось гарне, щоб ви бачили що компоненти відображаються.
- Тепер відкрийте layout.tsx, що лежить в теці app, та додайте до нього наступний код:
export default function RootLayout({ widget1, widget2, }) { return ( <html lang="en"> <body> {widget1} {widget2} </body> </html> ); }
Зверніть увагу, що тепер наші віджети передані через пропси і мають таку саму назву як і назва теки, що починається з @
- Тепер створіть новий файл в руті і покладіть туди наступний код:
export function delay({ data = 'hello world', error = '', delay = 1000 } = {}) { return new Promise((res, rej) => setTimeout(() => (error ? rej(error) : res(data)), delay) ); }
Це примітивна функція затримки, яка дає нам можливість почекати і отримати дані або кинути якусь помилку. З її допомогою ми протестуємо можливості наших роутів.
- В перший компонент додайте виклик функції без аргументів, а в другій, передайте якийсь текст у властивість error і не забудьте зробити await:
import { delay } from '../delay'; export default async function W2() { const sadString = await delay({ error: 'Sorry bro' }); return <>W2: {sadString}</>; }
Тепер у вас на екрані має з’явитися дуже не гарна помилка, яка руйнує весь застосунок:
Unhandled Runtime Error: Error: Error: Sorry bro
- Але це дуже просто виправити. В теці другого віджету створіть файл error.tsx з дефолтним експортом і якимось змістом. Збережіть файл і тепер, замість компоненту що не зміг завантажитися, ви побачите красиву, або не дуже помилку. Але весь інший контент залишається цілим і ваш користувач все ще може працювати з застосунком!
Залишився останній крок — індикація завантаження:
- В кожному з віджетів встановіть delay в 7000 та 4000 відповідно. Тепер ваша сторінка буде вантажитися 7 секунд, що геть не зручно для користувача. Зробімо завантаження паралельним!
- В теку з кожним віджетом додайте файл loading.tsx з дефолтним експортом. Якщо у вас з’явилася помилка default export is not a react component — перезапустіть сервер, або дайте компонентам різні імена.
❤️ Тепер, після завантаження сторінки, ви побачите, що наші віджети вантажаться індивідуально і виводяться на екран в міру надходження даних, скажіть краса?
❗️Пам’ятайте, що назви loading.tsx, page.tsx та error.tsx є зарезервованими і змінювати їх не можна.
Це був найпростіший і найменш цікавий приклад... Далі буде 😉
Код для погратися лежить тут (GitHub)
А наша спільнота тут (Телеграм)
Так стоп, а де ж обіцяні три слова?
На те, щоб написати щось трохи менш тривіальне ніж цей приклад у мене пішло пів дня і то довелося йти поміж крапельками, буквально на чуєчці. Тому, те що я хочу написати від щирого серця, ДОУ просто не пропустить (там дійсно три слова). Замість цього скажу так з NextJS ви сумувати точно не будете!
Немає коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів