Передача состояния между маршрутами

В библиотеке Page.js маршрутизация строится на основе управления URL и обработки переходов между различными состояниями приложения. Передача состояния между маршрутами — важная задача, особенно в одностраничных приложениях (SPA), где необходимо сохранять данные между переходами без использования серверного запроса или глобального хранилища.

Использование параметров URL

Наиболее простым способом передачи состояния является использование параметров URL. Page.js позволяет определять динамические сегменты маршрута с помощью :.

page('/profile/:userId', (ctx) => {
    console.log(ctx.params.userId);
});

Пример передачи состояния:

page('/dashboard', () => {
    const userId = 42;
    page.redirect(`/profile/${userId}`);
});

Здесь состояние userId передаётся через URL, и обработчик маршрута может получить его через ctx.params.

Плюсы:

  • Простота реализации
  • Поддержка прямых ссылок и закладок

Минусы:

  • Состояние становится видимым в URL
  • Не подходит для больших объектов или чувствительных данных

Использование query-параметров

Для передачи небольших данных можно использовать query-параметры, которые добавляются к URL после ?.

page('/search', (ctx) => {
    const query = new URLSearchParams(ctx.querystring);
    console.log(query.get('q')); // выводит поисковый запрос
});

page.redirect('/search?q=javascript');

Особенности:

  • Поддерживает сериализацию примитивных данных
  • Удобно для фильтров, поиска, пагинации

Ограничения:

  • Не подходит для сложных объектов без сериализации
  • URL может быстро разрастаться

Использование глобального состояния

Для передачи сложных объектов или временных данных между маршрутами удобно использовать глобальное состояние. Обычно это объект или singleton, доступный во всех обработчиках Page.js.

const state = {};

page('/step1', () => {
    state.user = { name: 'Ivan', age: 30 };
    page.redirect('/step2');
});

page('/step2', () => {
    console.log(state.user); // { name: 'Ivan', age: 30 }
});

Преимущества:

  • Поддержка любых объектов
  • Не зависит от URL

Недостатки:

  • Данные теряются при перезагрузке страницы
  • Не всегда удобно для больших приложений без централизованного хранилища

Использование sessionStorage и localStorage

Для сохранения состояния между переходами с возможностью перезагрузки страницы применяются веб-хранилища:

page('/step1', () => {
    sessionStorage.setItem('user', JSON.stringify({ name: 'Anna' }));
    page.redirect('/step2');
});

page('/step2', () => {
    const user = JSON.parse(sessionStorage.getItem('user'));
    console.log(user.name); // Anna
});

Различия между хранилищами:

  • sessionStorage — данные живут до закрытия вкладки
  • localStorage — данные сохраняются навсегда, пока их явно не удалить

Применение: временные данные, формы, корзины товаров.

Передача состояния через ctx в цепочках middleware

Page.js поддерживает цепочки middleware, что позволяет передавать состояние через объект ctx между обработчиками маршрутов:

page('/order/:id', addUserData, showOrder);

function addUserData(ctx, next) {
    ctx.user = { name: 'Sergey' };
    next();
}

function showOrder(ctx) {
    console.log(ctx.user.name); // Sergey
    console.log(ctx.params.id); // id заказа из URL
}

Преимущества:

  • Чёткая структура передачи данных между middleware
  • Изоляция состояния конкретного маршрута
  • Удобно для авторизации, проверки доступа, предварительной загрузки данных

Комбинированный подход

Часто используется комбинированный подход: URL для идентификаторов и query-параметров, ctx для промежуточных данных, а sessionStorage или глобальное состояние для больших объектов или временных данных. Например:

page('/checkout/:cartId', loadCart, validateUser, showCheckout);

function loadCart(ctx, next) {
    ctx.cart = JSON.parse(sessionStorage.getItem(ctx.params.cartId));
    next();
}

function validateUser(ctx, next) {
    if (!ctx.cart.user) {
        page.redirect('/login');
    } else {
        next();
    }
}

function showCheckout(ctx) {
    renderCheckoutPage(ctx.cart);
}

Такой подход обеспечивает:

  • Безопасность и читаемость URL
  • Лёгкую передачу больших данных между маршрутами
  • Контроль над состоянием на каждом этапе маршрутизации

Рекомендации по передаче состояния

  1. Минимизировать использование глобального состояния для избежания конфликтов и утечек памяти.
  2. Сериализовать данные при передаче через query-параметры или хранилище, чтобы избежать ошибок типов.
  3. Использовать ctx для промежуточных данных, особенно при цепочках middleware.
  4. Хранить чувствительные данные на стороне клиента временно, но не в URL.
  5. Разделять данные для разных маршрутов во избежание коллизий и нежелательного пересечения состояний.

Передача состояния между маршрутами в Page.js — это баланс между удобством, безопасностью и прозрачностью. Комбинация URL-параметров, ctx, глобального состояния и веб-хранилищ позволяет гибко управлять данными, сохраняя логику приложения чистой и предсказуемой.