← Назад к вопросам
Как сделать редирект пользователя на другую страницу?
2.0 Middle🔥 141 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как сделать редирект пользователя на другую страницу?
В React / Next.js: useRouter хук
// === Next.js App Router (рекомендуется) ===
'use client'; // клиентский компонент
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
export function RedirectComponent() {
const router = useRouter();
// Редирект после действия пользователя
function handleLogin() {
// ... обработка логина
router.push('/dashboard'); // переход на /dashboard
}
// Редирект при загрузке компонента
useEffect(() => {
if (!isAuthenticated) {
router.push('/login');
}
}, [isAuthenticated, router]);
return (
<button onClick={handleLogin}>
Log In
</button>
);
}
// === Next.js Pages Router (старый стиль) ===
import { useRouter } from 'next/router';
export function OldStyleRedirect() {
const router = useRouter();
function handleClick() {
router.push('/other-page');
}
return <button onClick={handleClick}>Go</button>;
}
// === Методы router ===
router.push('/path'); // переход обычный
router.replace('/path'); // замена в истории (back не будет работать)
router.prefetch('/path'); // предзагрузка страницы для быстрого перехода
router.back(); // назад в истории
router.forward(); // вперёд в истории
Простой React SPA (React Router)
// === Использование useNavigate из react-router-dom ===
import { useNavigate } from 'react-router-dom';
export function MyComponent() {
const navigate = useNavigate();
function handleClick() {
navigate('/about');
}
function goBack() {
navigate(-1); // вернуться на предыдущую страницу
}
function replaceHistory() {
navigate('/home', { replace: true }); // замена вместо добавления в историю
}
return (
<>
<button onClick={handleClick}>Go to About</button>
<button onClick={goBack}>Back</button>
<button onClick={replaceHistory}>Replace</button>
</>
);
}
// === Редирект при загрузке компонента ===
export function ProtectedPage() {
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
checkAuth().then((isAuth) => {
if (!isAuth) {
navigate('/login', { replace: true });
}
setIsLoading(false);
});
}, [navigate]);
if (isLoading) return <div>Loading...</div>;
return <div>Protected Content</div>;
}
// === Компонент <Navigate> для встроенных редиректов ===
import { Navigate } from 'react-router-dom';
export function PrivateRoute({ isAuthenticated, children }) {
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
return children;
}
// Использование:
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route
path="/dashboard"
element={
<PrivateRoute isAuthenticated={isAuth}>
<Dashboard />
</PrivateRoute>
}
/>
</Routes>
</BrowserRouter>
Vanilла JavaScript
// === Простой редирект через location ===
// Способ 1: window.location.href (полная перезагрузка страницы)
window.location.href = '/new-page';
// Способ 2: window.location.replace (замена в истории)
window.location.replace('/new-page');
// Способ 3: window.location.pathname (только путь)
window.location.pathname = '/new-page';
// === С задержкой ===
setTimeout(() => {
window.location.href = '/thank-you';
}, 2000); // редирект через 2 секунды
// === Редирект на внешний URL ===
window.location.href = 'https://example.com';
// === История браузера (History API) ===
history.pushState(
{ page: 1 }, // state object
'Title', // title
'/new-url' // новый URL
);
history.replaceState(null, '', '/replace-url');
history.back(); // эквивалент нажатия back button
history.forward(); // эквивалент нажатия forward button
history.go(-2); // вернуться на 2 страницы назад
Условные редиректы и защита маршрутов
// === Next.js: защита маршрутов через middleware ===
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth_token');
// Если пользователь не авторизован и хочет на /dashboard
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
// Если авторизован и пытается на /login
if (token && request.nextUrl.pathname === '/login') {
return NextResponse.redirect(new URL('/dashboard', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*', '/login'],
};
// === React Router: Route Guards ===
function ProtectedRoute({ isAuth, children }) {
return isAuth ? children : <Navigate to="/login" />;
}
function Routes() {
const [isAuth, setIsAuth] = useState(false);
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route
path="/dashboard"
element={
<ProtectedRoute isAuth={isAuth}>
<DashboardPage />
</ProtectedRoute>
}
/>
</Routes>
</BrowserRouter>
);
}
// === Программный редирект после проверки ===
export function LoginForm() {
const navigate = useNavigate();
const [error, setError] = useState('');
async function handleSubmit(e) {
e.preventDefault();
try {
const response = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify({ email, password }),
});
if (response.ok) {
// Успех — редирект на dashboard
navigate('/dashboard');
} else {
// Ошибка — показываем сообщение
setError('Invalid credentials');
}
} catch (err) {
setError('Network error');
}
}
return (
<form onSubmit={handleSubmit}>
<input type="email" />
<input type="password" />
{error && <p className="text-red-500">{error}</p>}
<button>Sign In</button>
</form>
);
}
Параметры и query strings при редиректе
// === Передача параметров ===
// Next.js
router.push('/search?q=javascript&page=2');
// React Router
navigate('/search?q=javascript&page=2');
// Vanilла JS
window.location.href = '/search?q=javascript&page=2';
// === Чтение параметров ===
// Next.js
import { useSearchParams } from 'next/navigation';
export function SearchPage() {
const searchParams = useSearchParams();
const q = searchParams.get('q');
const page = searchParams.get('page');
return <div>Searching for: {q}, page: {page}</div>;
}
// React Router
import { useSearchParams } from 'react-router-dom';
export function SearchPage() {
const [searchParams] = useSearchParams();
const q = searchParams.get('q');
return <div>Results for: {q}</div>;
}
// Vanilла JS
const params = new URLSearchParams(window.location.search);
const q = params.get('q');
Редирект со статус-кодами (SSR)
// === Next.js: редирект на сервере ===
export async function getServerSideProps() {
// Проверяем данные на сервере
const data = await fetchData();
if (!data.isValid) {
return {
redirect: {
destination: '/error',
permanent: false, // 307 вместо 308
},
};
}
return {
props: { data },
};
}
// === Next.js: постоянный редирект в next.config.js ===
const nextConfig = {
redirects: async () => [
{
source: '/old-page',
destination: '/new-page',
permanent: true, // 301 редирект
},
{
source: '/docs/:path*',
destination: '/help/:path*',
permanent: false, // 307 редирект
},
],
};
// === Next.js: редирект для всех неизвестных маршрутов ===
redirects: async () => [
{
source: '/:path*',
destination: '/404',
permanent: false,
},
];
Best Practices
// OK: использовать правильные инструменты для редиректов
// Next.js -> useRouter хук
const router = useRouter();
router.push('/page');
// React Router -> useNavigate хук
const navigate = useNavigate();
navigate('/page');
// NOT OK: window.location для SPA (полная перезагрузка)
window.location.href = '/page'; // слишком медленно!
// OK: использовать replace для определённых сценариев
router.push('/dashboard', { replace: true }); // логин -> dashboard (без back)
// OK: проверять авторизацию перед редиректом
if (!token) {
navigate('/login');
}
// NOT OK: редиректить без проверки в useEffect (бесконечный цикл)
useEffect(() => {
navigate('/page'); // будет срабатывать каждый раз!
}, []); // не забывай зависимости!
// OK: редирект с проверкой условия
useEffect(() => {
if (!user) {
navigate('/login');
}
}, [user, navigate]);