TanStack Router в процессе своего развития претерпевал значительные изменения API, что делает критически важным понимание breaking changes при обновлении проектов с одной версии на другую. Эти изменения могут затрагивать маршрутизацию, работу с хранилищем состояния маршрутов, загрузку данных и взаимодействие с хуками.
В ранних версиях TanStack Router маршруты описывались преимущественно
через объект RouteConfig, с возможностью указания
path, component и children.
Начиная с версии 2.x, структура была переработана:
Удаление RouteConfig в пользу декларативного
описания маршрутов через Route классы.
// Старый подход
const routes = [
{
path: "/users",
component: UsersPage,
children: [
{ path: ":id", component: UserDetailPage }
]
}
];
// Новый подход
const usersRoute = new Route({ path: "/users", component: UsersPage });
const userDetailRoute = new Route({ path: ":id", component: UserDetailPage });
usersRoute.addChildren([userDetailRoute]);
const router = new Router({ routes: [usersRoute] });Метод addChild заменил вложение через массив
children. Теперь вложенные маршруты создаются явно
через методы маршрута, что повышает читаемость и контроль над
конфигурацией.
Свойство index теперь обязательное для
индексных маршрутов. Ранее индексные маршруты определялись
отсутствием path, теперь нужно явно указывать
index: true.
В новых версиях изменился подход к хукам маршрутизации:
useRouteMatch был удален и заменен на
useMatch, которая возвращает информацию о текущем
совпадении маршрута.useRouter теперь предоставляет полный объект
маршрутизатора с методами navigate, preload,
refresh и доступом к всем зарегистрированным
маршрутам.Пример замены:
// Старый код
const match = useRouteMatch("/users/:id");
// Новый код
const match = useMatch("/users/:id");
const router = useRouter();
useNavigate теперь реализуется через объект
router.navigate вместо отдельного хука. Это унифицирует
навигацию для всех типов компонентов.В версии 1.x TanStack Router использовал loader на
уровне маршрута для асинхронной загрузки данных. В версии 2.x и
выше:
loader заменён на
loaderFn. Новое свойство принимает функцию,
возвращающую Promise с данными.router.// Старый синтаксис
const userLoader = async ({ params }) => {
return fetchUser(params.id);
}
// Новый синтаксис
const userLoaderFn = async ({ params, router }) => {
return fetchUser(params.id);
}
router.navigate вместо выбрасывания
исключений.В старых версиях маршрутизация и управление URL были более опосредованными:
router.push и router.replace заменены
на единый метод router.navigate, принимающий объект с
полями:
to — путь или имя маршрута,replace — логическое значение для замены текущего
состояния,params — параметры маршрута,query — query-параметры.router.navigate({ to: "/users/1", replace: true });
router.state.query, что требует явного чтения/записи вместо
автоматического связывания.Старые версии TanStack Router использовали глобальный объект
состояния маршрута, который мог содержать route.state. В
новых версиях:
route.state заменён на локальный и
глобальный стейт:
useLocalRouteState.router.state.Обновление состояния стало атомарным:
router.setState({ key: value }) вместо прямого
присваивания.
Breaking changes коснулись и типизации:
Route теперь строго типизированы.
params и query должны быть объявлены через
generic-параметры маршрута.Router требует декларации всех маршрутов с их типами
заранее.const usersRoute = new Route<{ id: string }>({ path: "/users/:id", component: UserDetailPage });
loader функции и переписать их под
loaderFn.useRouteMatch и
useNavigate на useMatch и
router.navigate.index: true для индексных маршрутов.Route и
использовать addChildren вместо вложенных массивов.router.state и useLocalRouteState.Эти изменения делают TanStack Router более предсказуемым и типобезопасным, но требуют внимательной проверки существующего кода при обновлении версий.