В современных приложениях на React часто возникает необходимость передавать параметры через URL. React Router предоставляет мощные средства для работы с параметрами маршрутов, однако при разработке на TypeScript важно обеспечить типобезопасность этих параметров, чтобы предотвратить ошибки во время компиляции и повысить надежность кода.
В React Router параметры маршрута задаются через двоеточие в строке пути:
import { BrowserRouter, Routes, Route } from "react-router-dom";
import UserPage from "./UserPage";
<BrowserRouter>
<Routes>
<Route path="/user/:userId" element={<UserPage />} />
</Routes>
</BrowserRouter>
В этом примере :userId является параметром маршрута. Без
TypeScript тип параметра неизвестен и воспринимается как
string | undefined. Для строгой типизации необходимо
использовать типы для этих параметров.
useParams с типамиХук useParams позволяет получить параметры маршрута в
компоненте:
import { useParams } from "react-router-dom";
interface UserParams {
userId: string;
}
const UserPage: React.FC = () => {
const { userId } = useParams<UserParams>();
return <div>Пользователь: {userId}</div>;
};
Здесь интерфейс UserParams определяет ожидаемые
параметры. TypeScript проверяет доступ к userId и
предотвращает ошибки, связанные с опечатками или отсутствием поля.
Параметры маршрута могут быть обязательными и необязательными:
<Route path="/product/:productId/:tab?" element={<ProductPage />} />
productId — обязательный параметр.tab — необязательный параметр (символ
?).Соответствующий интерфейс:
interface ProductParams {
productId: string;
tab?: string;
}
Использование useParams<ProductParams>() позволяет
корректно обработать оба типа параметров.
Все параметры, получаемые через URL, имеют тип string.
Часто требуется конвертировать их в другие типы:
interface ItemParams {
itemId: string;
}
const ItemPage: React.FC = () => {
const { itemId } = useParams<ItemParams>();
const numericId = Number(itemId);
if (isNaN(numericId)) {
return <div>Некорректный идентификатор</div>;
}
return <div>Элемент №{numericId}</div>;
};
Типизация через интерфейс гарантирует, что itemId всегда
присутствует как строка, а конвертация и проверка числа предотвращает
ошибки на ранней стадии.
При навигации через useNavigate также важно учитывать
типы параметров:
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
const goToUser = (id: number) => {
navigate(`/user/${id}`);
};
Использование типизированных аргументов помогает избежать ошибок, когда передается неправильный тип значения.
<Routes>
<Route path="/users/:userId" element={<UserPage />} />
<Route path="/users/:userId/posts/:postId" element={<PostPage />} />
</Routes>
Интерфейсы параметров для вложенных маршрутов:
interface PostParams {
userId: string;
postId: string;
}
const PostPage: React.FC = () => {
const { userId, postId } = useParams<PostParams>();
return (
<div>
Пользователь: {userId}, Пост: {postId}
</div>
);
};
Такой подход обеспечивает строгую проверку всех параметров на уровне компиляции, исключая ошибки доступа к неопределенным полям.
RouteObject для полной типизацииПри конфигурации маршрутов через объекты RouteObject
удобно создавать универсальные типы:
import { RouteObject } from "react-router-dom";
interface AppRoutes {
user: { userId: string };
post: { userId: string; postId: string };
}
const routes: RouteObject[] = [
{
path: "/user/:userId",
element: <UserPage />,
},
{
path: "/user/:userId/post/:postId",
element: <PostPage />,
},
];
Типы параметров могут быть использованы в комбинации с вспомогательными функциями генерации URL, что позволяет навигировать по приложению строго типизированным образом:
function buildUserUrl(params: AppRoutes["user"]) {
return `/user/${params.userId}`;
}
function buildPostUrl(params: AppRoutes["post"]) {
return `/user/${params.userId}/post/${params.postId}`;
}
Типобезопасность в React Router достигается через комбинацию
TypeScript-интерфейсов, хука
useParams, строгой конверсии
типов и типизированной генерации URL, что
делает работу с динамическими маршрутами безопасной и предсказуемой.