Восстановление состояния из URL

В веб-приложениях современного типа навигация часто строится вокруг URL, который не только определяет путь к конкретной странице, но и может содержать информацию о состоянии интерфейса. Библиотека Universal Router предоставляет гибкие механизмы для сопоставления URL с обработчиками маршрутов, что позволяет эффективно восстанавливать состояние приложения при загрузке страницы или переходе между маршрутами.

Основные принципы восстановления состояния

Восстановление состояния из URL предполагает, что каждый маршрут кодирует необходимую информацию для корректного отображения приложения. Это может включать:

  • Параметры пути (/users/:id)
  • Параметры запроса (?filter=active&page=2)
  • Фрагменты URL (#section1)

Universal Router поддерживает как статические, так и динамические маршруты, что обеспечивает возможность извлекать параметры пути и query-параметры прямо из URL.

Пример динамического маршрута с параметром пути:

import UniversalRouter from 'universal-router';

const routes = [
  {
    path: '/users/:id',
    action: ({ params }) => {
      return `Пользователь с ID: ${params.id}`;
    }
  }
];

const router = new UniversalRouter(routes);

router.resolve('/users/42').then(console.log); // Пользователь с ID: 42

В данном примере параметр id извлекается напрямую из URL, что позволяет восстановить состояние компонента, отображающего информацию о конкретном пользователе.

Работа с query-параметрами

Universal Router из коробки не парсит query-параметры, поэтому для извлечения состояния из URL необходимо использовать стандартные средства браузера или сторонние утилиты, например URLSearchParams.

function getQueryParams(url) {
  const searchParams = new URL(url, window.location.origin).searchParams;
  return Object.fromEntries(searchParams.entries());
}

const routes = [
  {
    path: '/search',
    action: ({ query }) => {
      return `Результаты поиска по запросу: ${query.q}`;
    }
  }
];

const router = new UniversalRouter(routes);

const url = '/search?q=javascript';
const query = getQueryParams(url);

router.resolve({ pathname: '/search', query }).then(console.log); 
// Результаты поиска по запросу: javascript

Здесь объект query содержит все параметры из строки запроса, что позволяет восстановить состояние интерфейса, например фильтры или сортировку данных.

Вложенные маршруты и восстановление комплексного состояния

Universal Router поддерживает вложенные маршруты, что особенно полезно при построении приложений с комплексной структурой, где состояние может зависеть от нескольких уровней URL.

const routes = [
  {
    path: '/users',
    children: [
      {
        path: '/:id',
        action: ({ params }) => `Профиль пользователя: ${params.id}`
      },
      {
        path: '/:id/settings',
        action: ({ params }) => `Настройки пользователя: ${params.id}`
      }
    ]
  }
];

const router = new UniversalRouter(routes);

router.resolve('/users/42/settings').then(console.log); 
// Настройки пользователя: 42

Вложенные маршруты позволяют восстанавливать состояние не только текущего представления, но и контекста родительских разделов приложения.

Асинхронные действия при восстановлении состояния

Очень часто восстановление состояния требует асинхронной загрузки данных из API. Universal Router поддерживает промисы внутри action-функций, что позволяет интегрировать восстановление состояния с сетевыми запросами.

const routes = [
  {
    path: '/posts/:id',
    async action({ params }) {
      const response = await fetch(`/api/posts/${params.id}`);
      const post = await response.json();
      return `Заголовок поста: ${post.title}`;
    }
  }
];

const router = new UniversalRouter(routes);

router.resolve('/posts/101').then(console.log);

Асинхронные маршруты обеспечивают плавное восстановление состояния даже при необходимости загрузки больших объемов данных.

Обработка состояния через объект context

Universal Router позволяет передавать объект context при вызове resolve. Это особенно удобно для передачи состояния приложения, которое не закодировано в URL, но нужно для восстановления интерфейса.

const routes = [
  {
    path: '/dashboard',
    action: ({ context }) => `Привет, ${context.userName}`
  }
];

const router = new UniversalRouter(routes);

router.resolve('/dashboard', { context: { userName: 'Алексей' } }).then(console.log); 
// Привет, Алексей

Передача context позволяет комбинировать информацию из URL и состояние приложения, что дает полный контроль над восстановлением интерфейса.

Практические рекомендации

  • Использовать параметры пути для критически важного состояния, которое должно быть доступно напрямую через URL.
  • Query-параметры применять для опциональных фильтров и сортировок.
  • Для асинхронного восстановления состояния выносить загрузку данных в async action.
  • Контекст (context) использовать для состояния, которое не должно быть видимо в URL, но необходимо для корректного отображения.

Эффективное восстановление состояния из URL с Universal Router позволяет создавать приложения с устойчивой навигацией, где каждый URL полностью определяет видимое состояние интерфейса, обеспечивая глубокую интеграцию с браузерной историей и возможность делиться ссылками на конкретное состояние приложения.