Промпты подтверждения

React Router — это библиотека для организации маршрутов в приложениях на React, позволяющая управлять отображением компонентов в зависимости от URL. Основной концепцией является сопоставление путей с компонентами.

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './Home';
import About from './About';

function App() {
  return (
    
      
        } />
        } />
      
    
  );
}
  • BrowserRouter отвечает за синхронизацию URL с историей браузера.
  • Routes содержит все маршруты приложения.
  • Route описывает путь (path) и компонент для рендеринга (element).

Динамические маршруты и параметры

React Router позволяет использовать параметры в URL, что особенно полезно для страниц деталей, профилей и товаров.

} />
  • :id — параметр маршрута.
  • В компоненте доступ к параметру осуществляется через хук useParams():
import { useParams } from 'react-router-dom';

function UserProfile() {
  const { id } = useParams();
  return 
Профиль пользователя с ID: {id}
; }

Навигация между маршрутами

Для перехода между страницами используется компонент Link и хук useNavigate.

import { Link, useNavigate } from 'react-router-dom';

function Navigation() {
  const navigate = useNavigate();

  const goToHome = () => {
    navigate('/');
  };

  return (
    
О сайте
); }
  • Link создает ссылку, которая не перезагружает страницу.
  • useNavigate позволяет программно изменять маршрут.

Промпты подтверждения (Navigation Prompt)

Иногда требуется предотвратить случайный уход со страницы с несохраненными изменениями. Для этого в React Router используется механизм промптов подтверждения.

Реализация с хуком usePrompt

import { useEffect } from 'react';
import { unstable_useBlocker as useBlocker } from 'react-router-dom';

function usePrompt(message, when = true) {
  const blocker = useBlocker(when);

  useEffect(() => {
    if (!blocker.state === 'blocked') return;

    const confirmNavigation = window.confirm(message);
    if (confirmNavigation) {
      blocker.proceed();
    } else {
      blocker.reset();
    }
  }, [blocker, message]);
}
  • useBlocker отслеживает попытки навигации.
  • window.confirm() выводит системное окно подтверждения.
  • proceed() и reset() управляют действием навигации.

Использование на форме

import { useState } from 'react';

function FormPage() {
  const [isDirty, setIsDirty] = useState(false);

  usePrompt('Вы действительно хотите покинуть страницу? Несохраненные изменения будут потеряны.', isDirty);

  return (
    
setIsDirty(true)} />
); }
  • isDirty отслеживает, были ли внесены изменения.
  • Промпт появляется только при попытке уйти с несохраненными данными.

Примечания по UX

  • Механизм window.confirm блокирует пользовательский поток, но стандартного способа кастомизации модального окна нет.
  • Для более гибкого UX можно создавать собственные модальные окна с состоянием и кнопками “Остаться” / “Покинуть страницу”.
  • Промпты должны срабатывать только при реальной необходимости — чрезмерное использование раздражает пользователей.

Совместимость и ограничения

  • React Router v6 и выше использует хуки для управления навигацией и блокировкой.
  • Метод useBlocker помечен как unstable и может меняться, поэтому для долгосрочных проектов рекомендуется контролировать версии библиотеки.
  • Промпты не блокируют закрытие вкладки браузера полностью, для этого используют событие beforeunload:
useEffect(() => {
  const handleBeforeUnload = (e) => {
    if (isDirty) {
      e.preventDefault();
      e.returnValue = '';
    }
  };
  window.addEventListener('beforeunload', handleBeforeUnload);
  return () => window.removeEventListener('beforeunload', handleBeforeUnload);
}, [isDirty]);
  • Это гарантирует предупреждение даже при закрытии вкладки или перезагрузке страницы.

Практические рекомендации

  • Использовать промпты только на страницах с формами или важными данными.
  • Комбинировать usePrompt и beforeunload для полной защиты от потери информации.
  • Проверять совместимость с текущей версией React Router перед использованием нестабильных хуков.
  • Всегда управлять состоянием isDirty корректно, чтобы не блокировать навигацию без необходимости.