Приходите и попробуйте ChatGpt бесплатно Плюс версия, мы платим за это 体验地址:https://chat.waixingyun.cn Вы можете присоединиться к технической группе внизу сайта и вместе находить ошибки.
В этой статье описывается, как реализовать компонент FormPrompt, который предупреждает пользователей, когда они пытаются уйти со страницы с несохраненными изменениями. В статье обсуждается, как справляться с подобными ситуациями, используя чистый JavaScript и событие beforeunload, а также решения, специфичные для React, такие как использование компонента Prompt в React Router v5, useBeforeUnload и нестабильность. Хорошей практикой взаимодействия с пользователем является добавление к пользователю диалогового окна подтверждения с просьбой подтвердить перенаправление, если у него есть несохраненные изменения формы. Отображая это приглашение, пользователи будут знать, что у них есть несохраненные изменения, и им будет разрешено сохранить или отменить свою работу, прежде чем продолжить перенаправление.
Ниже текст~
В сегодняшней цифровой среде важно обеспечить наилучшее взаимодействие с пользователем веб-приложений, требующих отправки форм. Распространенным источником раздражения пользователей является потеря несохраненных изменений из-за случайного выхода со страницы.
В этой статье будет показано, как реализовать FormPrompt
Компонент, который предупреждает пользователей, когда они пытаются уйти со страницы с несохраненными изменениями, эффективно улучшая общий пользовательский опыт. Мы обсудим, как использовать чистый JavaScript Чтобы справиться с такими ситуациями, используйте React Router v5
в Prompt компоненты, а также в React Router v6 используется в useBeforeUnload
и unstable_useBlocker
Зацепить конкретное решение.
Финальную версию приложения можно найти по адресу CodeSandbox Протестировано, код можно найти по адресу GitHub получено дальше.
мы создаем FormPrompt
компонент, в который нужно добавить beforeunload
Слушатель событий. Это событие будет запущено до того, как пользователь покинет страницу. Позвонив на мероприятие preventDefault
Метод, мы можем вызвать диалоговое окно подтверждения браузера. Только если в форме есть несохраненные изменения (по hasUnsavedChanges
указывает свойство), это диалоговое окно будет активировано.
// FormPrompt.js
import { useEffect } from "react";
export const FormPrompt = ({ hasUnsavedChanges }) => {
useEffect(() => {
const onBeforeUnload = (e) => {
if (hasUnsavedChanges) {
e.preventDefault();
e.returnValue = "";
}
};
window.addEventListener("beforeunload", onBeforeUnload);
return () => {
window.removeEventListener("beforeunload", onBeforeUnload);
};
}, [hasUnsavedChanges]);
};
В качестве примера мы будем использовать Contact
шагиспользуется в Этот компонент:
// Steps/Contact.js
import { forwardRef } from "react";
import { useForm } from "react-hook-form";
import { useAppState } from "../state";
import { Button, Field, Form, Input } from "../Forms";
import { FormPrompt } from "../FormPrompt";
export const Contact = forwardRef((props, ref) => {
const [state, setState] = useAppState();
const {
handleSubmit,
register,
formState: { isDirty },
} = useForm({
defaultValues: state,
mode: "onSubmit",
});
const saveData = (data) => {
setState({ ...state, ...data });
};
return (
<Form onSubmit={handleSubmit(saveData)} nextStep={"/education"}>
<FormPrompt hasUnsavedChanges={isDirty} />
<fieldset>
<legend>Contact</legend>
<Field label="First name">
<Input {...register("firstName")} id="first-name" />
</Field>
<Field label="Last name">
<Input {...register("lastName")} id="last-name" />
</Field>
<Field label="Email">
<Input {...register("email")} type="email" id="email" />
</Field>
<Field label="Password">
<Input {...register("password")} type="password" id="password" />
</Field>
<Button ref={ref}>Next {">"}</Button>
</fieldset>
</Form>
);
});
При вводе данных в поле формы и попытке перезагрузить страницу или перейти по внешнему URL-адресу перед сохранением изменений браузер отобразит диалоговое окно подтверждения.
Этот компонент достаточно хорош для нашего приложения, поскольку все его страницы являются частью формы. Однако в реальных ситуациях это не всегда так. Чтобы сделать наш пример более репрезентативным, мы добавим Home
Новый маршрут, который будет перенаправляться за пределы формы. Home
Компонент очень простой и отображает только приветствие домашней страницы.
// Home.js
export const Home = () => {
return <div>Welcome to the home page!</div>;
};
Нам также необходимо внести некоторые изменения в компонент приложения, чтобы он соответствовал этому новому маршруту.
// App.js
import { useRef } from "react";
import {
BrowserRouter as Router,
Routes,
Route,
NavLink,
} from "react-router-dom";
import { AppProvider } from "./state";
import { Contact } from "./Steps/Contact";
import { Education } from "./Steps/Education";
import { About } from "./Steps/About";
import { Confirm } from "./Steps/Confirm";
import { Stepper } from "./Steps/Stepper";
import { Home } from "./Home";
export const App = () => {
const buttonRef = useRef();
const onStepChange = () => {
buttonRef.current?.click();
};
return (
<div className="App">
<AppProvider>
<Router>
<div className="nav-wrapper">
<NavLink to={"/"}>Home</NavLink>
<Stepper onStepChange={onStepChange} />
</div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/contact" element={<Contact ref={buttonRef} />} />
<Route path="/education" element={<Education ref={buttonRef} />} />
<Route path="/about" element={<About ref={buttonRef} />} />
<Route path="/confirm" element={<Confirm />} />
</Routes>
</Router>
</AppProvider>
</div>
);
};
Мы видим, что когда мы вводим информацию в форму и переходим на домашнюю страницу, введенные данные не сохраняются и диалоговое окно подтверждения не появляется. Это связано с тем, что навигация обрабатывается React. Обработка маршрутизатора не срабатывает beforeunload
событие, в результате чего API браузера в этом случае становится недействительным. К счастью, Реакт Router v5 обеспечивает Prompt
компоненты,предупреждать пользователей перед тем, как покинуть страницу с несохраненными изменениями。该компоненты接受两个props
: when
и message
。 when
Свойство — это логическое значение, которое определяет, должно ли отображаться приглашение, а message
Свойства представляют собой текст, отображаемый пользователю.
При использовании подсказки поведение корректно при переходе к домашнему маршруту, но когда пользователь вводит данные формы и переходит к следующему шагу, также появляется диалоговое окно подтверждения. Это нежелательно, поскольку мы сохраняем данные формы при переходе к следующему шагу.
Для решения этой задачи нам необходимо проверить следующее URL Это один из шагов формы перед проверкой несохраненных изменений. Можно использовать message
Свойство для достижения этой цели также может быть функцией. Первый параметр этой функции — следующая позиция. Если функция возвращает true
, то переход к следующему разрешен URL; в противном случае он может вернуть строку для отображения приглашения.
// FormPrompt.js
import { useEffect } from "react";
import { Prompt } from "react-router-dom";
const stepLinks = ["/contact", "/education", "/about", "/confirm"];
export const FormPrompt = ({ hasUnsavedChanges }) => {
useEffect(() => {
const onBeforeUnload = (e) => {
if (hasUnsavedChanges) {
e.preventDefault();
e.returnValue = "";
}
};
window.addEventListener("beforeunload", onBeforeUnload);
return () => {
window.removeEventListener("beforeunload", onBeforeUnload);
};
}, [hasUnsavedChanges]);
const onLocationChange = (location) => {
if (stepLinks.includes(location.pathname)) {
return true;
}
return "You have unsaved changes, are you sure you want to leave?";
};
return <Prompt when={hasUnsavedChanges} message={onLocationChange} />;
};
Благодаря этим изменениям мы можем безопасно перемещаться между этапами формы и получать предупреждения при попытке выйти из формы без сохраненных изменений.
элементы были удалены и unstable_usePrompt
Крючок 6.7.0 версия добавлена. Как следует из названия, реализация перехватчика может быть изменена и еще не документирована. Однако для нашего варианта использования это должно работать.
Мы можем использовать этот крючок для репликации версии 5. Prompt поведение компонента, но сначала нам нужно настроить наш App компоненты для использования нового маршрутизатора данных в том виде, в котором они есть. unstable_usePrompt
Это необходимо для работы крючка.
// App.js
import { useRef } from "react";
import { createBrowserRouter, RouterProvider, Outlet } from "react-router-dom";
import { AppProvider } from "./state";
import { Contact } from "./Steps/Contact";
import { Education } from "./Steps/Education";
import { About } from "./Steps/About";
import { Confirm } from "./Steps/Confirm";
import { Stepper } from "./Steps/Stepper";
import { Home } from "./Home";
export const App = () => {
const buttonRef = useRef();
const onStepChange = () => {
buttonRef.current?.click();
};
const router = createBrowserRouter([
{
element: (
<>
<Stepper onStepChange={onStepChange} />
<Outlet />
</>
),
children: [
{
path: "/",
element: <Home />,
},
{
path: "/contact",
element: <Contact ref={buttonRef} />,
},
{ path: "/education", element: <Education ref={buttonRef} /> },
{ path: "/about", element: <About ref={buttonRef} /> },
{ path: "/confirm", element: <Confirm /> },
],
},
]);
return (
<div className="App">
<AppProvider>
<RouterProvider router={router} />
</AppProvider>
</div>
);
};
мы используем createBrowserRouter
функция для создания маршрутизатора. Обратите внимание, что Stepper
Отдельного пути нет, все остальные маршруты являются его дочерними маршрутами. Он действует как компонент макета и отображается на каждой странице. Содержимое каждой страницы отображается в специальном Outlet
Расположение компонента. Чтобы упростить App Logic, мы также перемещаем ссылку навигации по домашней странице в Stepper
середина.
После завершения настройки мы можем реализовать функцию блокировки перенаправления. Сначала мы проходим FormPrompt
используется Введено в версии 6.6 useBeforeUnload
крючок на замену onbeforeunload
логика.
// FormPrompt.js
import { useEffect, useCallback, useRef } from "react";
import { useBeforeUnload } from "react-router-dom";
const stepLinks = ["/contact", "/education", "/about", "/confirm"];
export const FormPrompt = ({ hasUnsavedChanges }) => {
useBeforeUnload(
useCallback(
(event) => {
if (hasUnsavedChanges) {
event.preventDefault();
event.returnValue = "";
}
},
[hasUnsavedChanges]
),
{ capture: true }
);
return null;
};
Это изменение упрощает внешний вид нашего компонента. Теперь мы можем добавить пользовательский. usePrompt
крючки и лайк версии 5в Prompt Используйте его как компонент.
// FormPrompt.js
import { useEffect, useCallback, useRef } from "react";
import {
useBeforeUnload,
unstable_useBlocker as useBlocker,
} from "react-router-dom";
const stepLinks = ["/contact", "/education", "/about", "/confirm"];
export const FormPrompt = ({ hasUnsavedChanges }) => {
const onLocationChange = useCallback(
({ nextLocation }) => {
if (!stepLinks.includes(nextLocation.pathname) && hasUnsavedChanges) {
return !window.confirm(
"You have unsaved changes, are you sure you want to leave?"
);
}
return false;
},
[hasUnsavedChanges]
);
usePrompt(onLocationChange, hasUnsavedChanges);
useBeforeUnload(
useCallback(
(event) => {
if (hasUnsavedChanges) {
event.preventDefault();
event.returnValue = "";
}
},
[hasUnsavedChanges]
),
{ capture: true }
);
return null;
};
function usePrompt(onLocationChange, hasUnsavedChanges) {
const blocker = useBlocker(hasUnsavedChanges ? onLocationChange : false);
const prevState = useRef(blocker.state);
useEffect(() => {
if (blocker.state === "blocked") {
blocker.reset();
}
prevState.current = blocker.state;
}, [blocker]);
}
useBlocker
Хук принимает в качестве аргумента логическую или блокирующую функцию, что-то вроде Prompt
Компоненты message
свойство. Одним из параметров функции является следующая позиция, мы UseIt определяет, покидает ли пользователь нашу форму. В этом случае мы используем функцию браузера window.confirm
Метод отображает диалоговое окно с просьбой подтвердить перенаправление или отменить его. Наконец, мы usePrompt
Логика блокировки абстрагируется в перехватчике, и состояние блокировщика управляется.
Мы можем проверить, что FormPrompt работает должным образом, перейдя к шагу контакта, заполнив некоторые поля и щелкнув элемент домашней навигации. Мы увидим диалоговое окно подтверждения с вопросом, хотим ли мы покинуть страницу.
Таким образом, внедрение диалоговых окон подтверждения для несохраненных изменений формы является важной практикой для улучшения пользовательского опыта. В этой статье показано, как создать FormPrompt Компонент, предупреждающий пользователей, когда они пытаются уйти со страницы с несохраненными изменениями. Мы рассмотрели, как справиться с этой ситуацией, используя чистый JavaScript, используя beforeunload
событиеи вReactиспользуется вReact Router v5в Prompt Компоненты и React Router v6в useBeforeUnload и unstable_useBlocker
крюк. Включив эту функцию в свои формы, вы можете помочь пользователям избежать разочарования, связанного с потерей несохраненной работы.
Невозможно узнать возможные ошибки в реальном времени после развертывания кода. Чтобы впоследствии устранить эти ошибки, на логирование уходит много времени. Для отладки я хотел бы порекомендовать вам полезный инструмент для мониторинга ошибок. Fundebug。
оригинальный:https://claritydev.net/blog/display-warning-for-unsaved-form-...