Контекст аутентификации

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

Создание контекста аутентификации

Для начала необходимо создать контекст с помощью стандартного API React:

import { createContext, useContext, useState } from 'react';

const AuthContext = createContext(null);

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);

  const login = async (credentials) => {
    // Здесь реализуется логика аутентификации
    const authenticatedUser = await fakeAuth(credentials);
    setUser(authenticatedUser);
  };

  const logout = () => {
    setUser(null);
  };

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => useContext(AuthContext);

Ключевые моменты:

  • AuthContext хранит состояние текущего пользователя.
  • login и logout предоставляют методы управления сессией.
  • useAuth является кастомным хуком для доступа к контексту в любом компоненте.

Интеграция с маршрутизатором

TanStack Router поддерживает использование loader-функций и хуков для проверки состояния аутентификации перед рендерингом маршрутов. Например:

import { createRouter, RouterProvider, route } from '@tanstack/router';
import { useAuth } from './AuthContext';

const Home = () => <div>Главная страница</div>;
const Dashboard = () => <div>Панель пользователя</div>;
const Login = () => <div>Страница входа</div>;

const requireAuth = async ({ context }) => {
  const { user } = context.auth;
  if (!user) {
    throw redirect('/login');
  }
  return user;
};

const router = createRouter({
  context: {
    auth: useAuth()
  },
  routes: [
    route({ path: '/', component: Home }),
    route({
      path: '/dashboard',
      component: Dashboard,
      loader: requireAuth
    }),
    route({ path: '/login', component: Login })
  ]
});

export const App = () => (
  <AuthProvider>
    <RouterProvider router={router} />
  </AuthProvider>
);

Особенности реализации:

  • Контекст аутентификации передается в конфигурацию маршрутизатора через context.
  • Loader-функция requireAuth проверяет наличие пользователя и при отсутствии выполняет редирект.
  • Такой подход позволяет разделять маршруты на публичные и защищенные, сохраняя чистую архитектуру приложения.

Динамическое обновление состояния аутентификации

TanStack Router поддерживает реактивное обновление маршрутов при изменении контекста. Это позволяет автоматически перенаправлять пользователя при изменении состояния сессии:

import { useEffect } from 'react';
import { useRouter } from '@tanstack/router';
import { useAuth } from './AuthContext';

const AuthListener = () => {
  const router = useRouter();
  const { user } = useAuth();

  useEffect(() => {
    if (!user) {
      router.navigate('/login');
    } else {
      router.navigate('/dashboard');
    }
  }, [user, router]);

  return null;
};

Здесь важно:

  • Хук useEffect следит за состоянием пользователя и перенаправляет при изменении.
  • Это обеспечивает мгновенную реакцию интерфейса на логин или логаут без ручного обновления маршрутов.

Работа с правами доступа и ролями

Контекст аутентификации можно расширять для поддержки ролей и прав доступа:

const requireRole = (role) => async ({ context }) => {
  const { user } = context.auth;
  if (!user || user.role !== role) {
    throw redirect('/login');
  }
  return user;
};

route({
  path: '/admin',
  component: AdminPanel,
  loader: requireRole('admin')
});
  • Функция requireRole создает loader, проверяющий роль пользователя перед доступом к маршруту.
  • Такой подход позволяет гибко управлять правами доступа на уровне маршрутов без дублирования кода.

Кеширование и восстановление сессии

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

useEffect(() => {
  const storedUser = localStorage.getItem('user');
  if (storedUser) {
    setUser(JSON.parse(storedUser));
  }
}, []);

useEffect(() => {
  if (user) {
    localStorage.setItem('user', JSON.stringify(user));
  } else {
    localStorage.removeItem('user');
  }
}, [user]);
  • Состояние пользователя автоматически сохраняется и восстанавливается при перезагрузке.
  • Позволяет маршрутизатору корректно отрисовывать защищенные маршруты даже после обновления страницы.

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