Перенаправление в React Router: Navigate и useNavigate

Почему это важно
При создании веб-приложений приватные страницы (например, панель управления) должны быть доступны только авторизованным пользователям. Если неавторизованный посетитель пытается открыть защищённую страницу, приложение должно перенаправить его на страницу входа и после успешного входа вернуть обратно — это улучшает UX и безопасность.
Создание React-приложения
В примерах используется React Router v6. Для начала создайте приложение:
npx create-react-app react-redirectУстановите React Router:
npm install react-router-domПростой пример страницы входа (Login)
Ниже упрощённый, исправленный пример компонента Login. Он демонстрирует хранение состояния аутентификации в localStorage (это удобно для демо, но не рекомендуется для реального продакшена без дополнительных мер безопасности).
import { useState } from "react";
import { useNavigate, useLocation } from "react-router-dom";
const Login = () => {
const navigate = useNavigate();
const location = useLocation();
// Вернём пользователя на страницу, с которой пришли
const from = location.state?.from?.pathname || "/dashboard";
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
// Используем строку "true"/"false" в localStorage
const [authenticated, setAuthenticated] = useState(
localStorage.getItem("authenticated") === "true"
);
const users = [{ username: "Jane", password: "testpassword" }];
const handleSubmit = (e) => {
e.preventDefault();
const account = users.find((user) => user.username === username);
if (account && account.password === password) {
localStorage.setItem("authenticated", "true");
setAuthenticated(true);
// После успешного входа возвращаем пользователя туда, откуда он пришёл
navigate(from, { replace: true });
} else {
alert("Неверный логин или пароль");
}
};
return (
Welcome Back
);
};
export default Login;Важно: localStorage подходит для демо и простых приложений, но токены в localStorage уязвимы к XSS. В продакшене стоит рассмотреть HTTP-only cookies или защищённое хранилище.
Простая страница Dashboard
const Dashboard = () => {
return (
Welcome to your Dashboard
);
};
export default Dashboard;Настройка маршрутов в index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Login from "./Login";
import Dashboard from "./Dashboard";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
} />
} />
} />
);Как сделать маршрут защищённым
Частый паттерн — вынести логику защиты в отдельный компонент высшего порядка (ProtectedRoute). Это делает маршрутизацию чистой и повторно используемой.
import { Navigate, Outlet } from "react-router-dom";
const ProtectedRoute = () => {
const isAuth = localStorage.getItem("authenticated") === "true";
if (!isAuth) {
// Перенаправляем на /login и сохраняем текущий путь в state
return ;
}
return ; // Рендерит вложенные маршруты (например, dashboard)
};
export default ProtectedRoute;Пример использования ProtectedRoute в Routes:
} />
}>
} />
Перенаправление с помощью Navigate
Navigate — декларативный способ. Если компонент понимает, что пользователь не авторизован, он возвращает
import { Navigate } from "react-router-dom";
if (!authenticated) {
return ;
}replace используется, чтобы не добавлять запись в историю браузера — это удобно для защиты страниц.
Перенаправление с помощью useNavigate
useNavigate — императивный API, даёт функцию navigate(). Это удобно при обработке событий (например, после submit формы).
const navigate = useNavigate();
// После успешного входа
navigate("/dashboard");
// Или вернуться назад в истории
navigate(-1);В примере выше в Login мы использовали navigate(from, { replace: true }) чтобы вернуть пользователя на страницу, с которой он пришёл.
Когда возвращать на предыдущую страницу vs на фиксированную
- Если пользователь пытался открыть конкретную защищённую страницу (например, /settings), обычно стоит вернуть его именно туда.
- Если логин инициирован с главной или ландинговой страницы, более предсказуемо отправить пользователя в dashboard.
Реализация через state (location.state.from) — надёжный и распространённый паттерн.
Альтернативные подходы и советы
- React Context + централизованная логика аутентификации: храните статус в Context и обновляйте от центра; это удобнее, чем читать localStorage в каждом компоненте.
- Защищённые cookie (HTTP-only) + серверная валидация: безопаснее для токенов.
- Серверный рендеринг (SSR) требует других механизмов защиты маршрутов (middleware на сервере).
Чек-лист для команды перед выпуском
- Разработчик: реализовал ProtectedRoute и тестовые сценарии.
- Ревьюер: проверил случаи перенаправления и поведение кнопки “Назад” в браузере.
- Тестировщик: проверил 1) неавторизованный доступ, 2) переход после успешного логина, 3) неудачный логин.
- DevOps: убедился, что окружение использует HTTPS и заголовки безопасности.
Краткий сниппет-справочник
- Navigate (декларативно):
return ;- useNavigate (императивно):
const navigate = useNavigate();
navigate('/dashboard');- Вернуть на предыдущую страницу:
navigate(-1);- Вернуть на страницу, откуда пришли:
// В ProtectedRoute: Navigate to="/login" state={{ from: location }}
// В Login после успеха:
navigate(from, { replace: true });Безопасность и приватность
Важно помнить:
- localStorage не защищён от XSS. Не храните в нём чувствительные токены без дополнительной защиты.
- Для соответствия требованиям приватности (например, GDPR) храните минимально необходимые данные и обеспечьте механизмы удаления данных по запросу пользователя.
- Для аутентификации в продакшене используйте HTTP-only cookies или серверную сессию с CSRF-защитой.
Критерии приёмки
- Неавторизованный пользователь перенаправляется на /login при попытке открыть защищённый маршрут.
- После успешного логина пользователь возвращается на страницу, с которой он пришёл (или на /dashboard, если исходный путь отсутствует).
- Кнопка “Назад” в браузере не приводит к зацикливанию перенаправлений (использован replace там, где нужно).
Распространённые ошибки и когда подходы не работают
- Хранение токена в localStorage делает приложение уязвимым к XSS.
- Если вы используете SSR и клиентский ProtectedRoute, защита будет видна пользователю на клиенте до полного рендера — лучше делать проверку на сервере.
- При некорректном сохранении state.from пользователь может потерять текущий контекст и попасть не туда, откуда пришёл.
Краткий глоссарий
- Navigate: декларативный компонент для перенаправления в React Router v6.
- useNavigate: хук, возвращающий функцию navigate для императивных переходов.
- ProtectedRoute: паттерн для защиты маршрутов, обычно реализуется через wrapper-компонент.
Итог
Перенаправление в React Router v6 можно выполнять декларативно (Navigate) или императивно (useNavigate). Для защищённых маршрутов удобен паттерн ProtectedRoute + передача origin через location.state. В продакшене обращайте внимание на хранение токенов, безопасность и UX при возврате пользователя на исходную страницу.
Важно: в реальном приложении используйте централизованный менеджер аутентификации (Context, Redux, или сторонний провайдер), защищённое хранение токенов и серверную валидацию.
Похожие материалы
Градиенты в Canva: добавить и настроить
Ошибка Disabled accounts can't be contacted в Instagram
Генерация случайных чисел в Google Sheets
Прокручиваемые скриншоты в Windows 11
Как установить корпусной вентилятор в ПК