@blzrov

Prompt-компонент на весь сайт?

Необходимо сделать один компонент, который будет вставлен в App container.
Компонент должен следить, что если юзер начал заполнять форму, инпуты, текстареа, что угодно, но потом хочет перейти на другую страницу, то должен вылезать Prompt с подтверждением. На сайте есть как страницы с формами, инпутами, текстареями, и без ничего. Дополнительно желательно следить на фетчами, так как где то после кнопки с типом button происходит редирект. Где то происходит подгрузка текста в инпуты. Буду рад подсказке куда двигаться, на данный момент придумал нечто такое
function MyPrompt() {
  const [isBlock, setIsBlock] = React.useState(false);
  const [text, setText] = React.useState(false);
  const location = useLocation();
  React.useEffect(() => {
    let timer = setTimeout(function f() {
      if (!Boolean(document.querySelector("textarea")?.value || false)) {
        setIsBlock(false);
        timer = setTimeout(f, 100);
      } else {
        if (!text) setText(document.querySelector("textarea")?.value);
        if (text != document.querySelector("textarea")?.value) setIsBlock(true);
        timer = setTimeout(f, 100);
      }
    }, 100);

    return () => {
      setIsBlock(false);
      clearTimeout(timer);
    };
  }, [location.pathname]);

  return (
    <Prompt
      when={isBlock}
      message={() => "Вы точно хотите покинуть страницу?"}
    />
  );
}
  • Вопрос задан
  • 112 просмотров
Пригласить эксперта
Ответы на вопрос 2
@ijesusyt
Похоже, вы уже написали компонент под названием MyPrompt, который отображает подсказку подтверждения, когда пользователь пытается уйти со страницы с формой. Этот компонент использует компонент Prompt из библиотеки react-router-dom для отображения подсказки подтверждения, а также использует хук useLocation из той же библиотеки для отслеживания текущего местоположения пользователя.

Компонент MyPrompt также использует хуки useState и useEffect из React для управления своим состоянием и выполнения побочных эффектов. Хук useState используется для управления переменными состояния isBlock и text, а хук useEffect используется для настройки таймера, который проверяет значение элемента textarea на странице каждые 100 миллисекунд. Если textarea имеет непустое значение, для переменной состояния isBlock устанавливается значение true, что приводит к тому, что компонент Prompt отображает подсказку подтверждения.

Чтобы вставить этот компонент в контейнер приложения, вы можете просто визуализировать его, как любой другой компонент. Например:
function App() {
  return (
    <div className="App">
      <MyPrompt />
      {/* other components go here */}
    </div>
  );
}
Ответ написан
Комментировать
ae_ph
@ae_ph
I'm a owl )
Объяснение:
Я изменил имя переменной состояния isBlock на isBlocking, чтобы было понятнее, что она представляет.
Добавил прослушиватель событий к событию beforeunload, который будет запущен, когда пользователь попытается покинуть страницу.
Добавил этот прослушиватель событий в хук useEffect, чтобы его можно было очистить при размонтировании компонента.
Добавил функцию handleFormChange, которая будет запускаться каждый раз при изменении формы, она проверяет значение ввода или текстового поля, если оно больше 0, оно устанавливает для isBlocking значение true, в противном случае — значение false.
Добавил событие onchange в форму и текстовое поле и событие onClick на кнопке отмены, это вызовет функцию handleFormChange, а также позволит пользователю отменить и покинуть страницу без каких-либо подсказок.
Также добавил в форму кнопку отправки и удалил useEffect, который опрашивал элемент textarea, и setTimeout, который использовался для этого.
Также добавил сообщение к событию beforeunload, которое будет отображаться как подсказка для пользователя с просьбой подтвердить, хотят ли они покинуть страницу.

Этот обновленный код теперь будет проверять наличие изменений в форме и текстовой области и предлагать пользователю подтвердить, хотят ли они покинуть страницу, если есть какие-либо несохраненные изменения.
Это также позволяет пользователю отменить и покинуть страницу без каких-либо подсказок, а также добавлена ​​кнопка отправки.

function MyPrompt() {
  const [isBlocking, setIsBlocking] = React.useState(false);
  const location = useLocation();

  const handleBeforeUnload = (event) => {
    if (isBlocking) {
      event.preventDefault();
      event.returnValue = "Are you sure you want to leave?";
    }
  };

  React.useEffect(() => {
    window.addEventListener("beforeunload", handleBeforeUnload);

    return () => {
      window.removeEventListener("beforeunload", handleBeforeUnload);
    };
  }, [isBlocking]);

  const handleFormChange = (event) => {
    if (event.target.value.length > 0) {
      setIsBlocking(true);
    } else {
      setIsBlocking(false);
    }
  };

  return (
    <div>
      <form onChange={handleFormChange}>
        <input type="text" placeholder="Type something here" />
        <textarea placeholder="Type something here"></textarea>
        <button type="submit">Submit</button>
        <button type="button" onClick={() => setIsBlocking(false)}>Cancel</button>
      </form>
    </div>
  );
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы