Создание и использование контекста

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

Основы контекста маршрута

Контекст маршрута в TanStack Router создаётся через createRouteContext и привязывается к конкретному маршруту. Это позволяет каждому маршруту иметь собственный набор данных, доступный всем дочерним компонентам. Контекст работает подобно React Context, но оптимизирован для маршрутизации и асинхронного получения данных.

Пример создания контекста для маршрута:

import { createRouteContext } from '@tanstack/router';

const UserContext = createRouteContext({
  // тип данных, хранимых в контексте
  defaultValue: {
    user: null,
    setUser: () => {}
  }
});

Здесь defaultValue определяет начальное состояние контекста. Контекст можно расширять и изменять, добавляя методы для обновления состояния.

Привязка контекста к маршруту

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

import { Route } from '@tanstack/router';

const userRoute = new Route({
  path: '/user',
  component: UserComponent,
  context: UserContext
});

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

Использование контекста в компонентах

Для работы с контекстом внутри компонента маршрута используется хук useRouteContext. Он обеспечивает типизированный и безопасный доступ к данным и методам контекста:

import { useRouteContext } from '@tanstack/router';

function UserComponent() {
  const { user, setUser } = useRouteContext(UserContext);

  return (
    <div>
      <h1>{user?.name || 'Гость'}</h1>
      <button onCl ick={() => setUser({ name: 'Иван' })}>Войти как Иван</button>
    </div>
  );
}

Хук автоматически подписывает компонент на изменения контекста. При обновлении состояния компонента, использующие контекст, будут перерендерены только при изменении значимых данных, что оптимизирует производительность.

Контексты и вложенные маршруты

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

const profileRoute = new Route({
  path: '/profile',
  component: ProfileComponent,
  parent: userRoute // наследует UserContext
});

function ProfileComponent() {
  const { user } = useRouteContext(UserContext);
  return <p>Профиль пользователя: {user?.name}</p>;
}

Наследование контекста упрощает управление состоянием на уровне группы маршрутов, избегая дублирования данных и функций.

Динамическое создание контекста

Контексты могут создаваться динамически при необходимости асинхронной загрузки данных:

const PostContext = createRouteContext({
  defaultValue: { post: null },
  async load({ params }) {
    const response = await fetch(`/api/posts/${params.id}`);
    const post = await response.json();
    return { post };
  }
});

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

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

  • Для глобальных данных, доступных на нескольких маршрутах, лучше создавать отдельный контекст на верхнем уровне маршрутизатора.
  • Контексты должны быть минимальными, содержать только данные, необходимые для маршрута и его дочерних компонентов, чтобы избежать лишних перерендеров.
  • Использование асинхронного метода load позволяет интегрировать TanStack Router с API без необходимости отдельного состояния в компонентах.
  • Изменение данных контекста через предоставленные функции обеспечивает централизованное управление состоянием маршрута и упрощает тестирование компонентов.

Контексты в TanStack Router — это мощный инструмент для построения структурированных и поддерживаемых маршрутов с локальным и глобальным состоянием, позволяющий управлять данными на уровне маршрутов без необходимости глобального состояния или сложного пробрасывания props.