Передача данных между хуками

Navigo — это легковесный роутер для JavaScript, позволяющий управлять маршрутизацией в одностраничных приложениях. Одной из ключевых задач при работе с Navigo является передача данных между различными хуками (функциями-обработчиками маршрутов) без необходимости использования глобальных переменных или сторонних хранилищ состояния.


Типы хуков и их роли

Navigo поддерживает несколько типов хуков:

  1. before — выполняется перед обработкой маршрута. Позволяет перехватывать навигацию, проверять условия или подготавливать данные.
  2. after — вызывается после того, как маршрут был успешно обработан.
  3. on — основной обработчик маршрута, в котором выполняется логика отображения контента.
  4. hooks в глобальном роутере — можно задать на уровне router.hooks({ before, after }), чтобы они применялись ко всем маршрутам.

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


Использование объекта context для передачи данных

Основной подход к обмену данными между хуками — использование контекста маршрута. В Navigo this внутри хука ссылается на роутер, но для безопасной передачи данных лучше использовать параметр params и возвращаемый объект из before:

const router = new Navigo("/");

router.on("/profile/:id", (params, query) => {
    console.log("ID пользователя:", params.userId);
    console.log("Данные из before:", params.preloadedData);
}).before((done, params) => {
    fetch(`/api/user/${params.id}`)
        .then(res => res.json())
        .then(data => {
            params.preloadedData = data; // добавляем данные в params
            done(); // продолжить обработку маршрута
        });
});

Здесь ключевой момент: объект params можно расширять любыми данными, которые затем будут доступны в основном обработчике on.


Передача данных между before и after

after-хуки часто используют для логирования, аналитики или обновления UI после смены маршрута. Данные из before или основного обработчика можно передавать через объект params или через this.lastRouteResolved, если требуется доступ к предыдущему маршруту.

Пример с after:

router.on("/dashboard", (params) => {
    params.dashboardData = { widgets: ["chart", "table"] };
}).after((params) => {
    console.log("Данные из on-хука:", params.dashboardData);
});

Важно: after получает те же параметры, что и основной обработчик, поэтому любые данные, добавленные к params в on или before, доступны и здесь.


Асинхронные хуки и управление потоком

При работе с асинхронными операциями важно использовать done() в before для контроля продолжения маршрута:

router.on("/reports/:year", (params) => {
    console.log("Отчет за год:", params.year);
    console.log("Данные отчета:", params.reportData);
}).before((done, params) => {
    fetch(`/api/reports/${params.year}`)
        .then(r => r.json())
        .then(data => {
            params.reportData = data;
            done();
        })
        .catch(() => {
            done(false); // прерываем навигацию при ошибке
        });
});

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

  • Любые данные, добавленные к params до вызова done(), становятся доступными в обработчике маршрута.
  • Передача данных через params исключает необходимость глобального состояния или хранилища.
  • Прерывание маршрута (done(false)) позволяет защитить приложение от некорректных переходов.

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

Для случаев, когда данные должны быть доступны всем маршрутам, можно использовать свойства роутера:

router.hooks({
    before: (done, params) => {
        router.sharedData = { user: { id: 1, name: "Alex" } };
        done();
    },
    after: (params) => {
        console.log("Глобальные данные:", router.sharedData);
    }
});

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


Рекомендации по организации данных между хуками

  1. Минимизировать глобальные переменные. Использовать params и свойства роутера.
  2. Явно передавать данные через params, особенно если они специфичны для маршрута.
  3. Использовать асинхронные хуки для загрузки данных с сервера до рендера страницы.
  4. Сохранять чистоту данных между переходами, очищая параметры при необходимости.
  5. Использовать before для предварительной подготовки данных, а after для логирования и побочных эффектов.

Передача данных через хуки в Navigo позволяет создавать управляемые, модульные маршруты с минимальной связностью и высокой предсказуемостью поведения приложения.