У меня есть приложение на Ionic react, есть две презентационных компоненты, один отрисовывает другой, второй модал. Есть два хука, один отвечает за открытие и закрытие модала, второй за логику обработки формы, мне нужно проверить, не загрязнена ли форма при вводе поля, мне нужно, чтобы значение isDirty обновлялось немедленно, потому что я хочу передать его измененное значение из useModalForm через MyModal в хук useModalHandler в качестве аргумента функции closeModal, так что, когда пользователь начинает вводить значение в поле, isDirty менялось на true, и если закрыть форму без сохранения, по условию должен вызываться myAlert, который предупреждает о потере данных.
Но на практике isDirty не меняет значение в момент ввода, в чем может быть проблема?
import React from "react";
import {
IonModal,
IonHeader,
IonToolbar,
IonButton,
IonIcon,
IonContent,
IonItem,
IonLabel,
IonInput,
IonCard,
IonCardContent,
} from "@ionic/react";
import UnsavedChangesAlert from "../Alert/MyAlert";
interface MyModalProps {
isOpen: boolean;
closeModal: (isDirty: boolean) => void;
errors: any;
isDirty: boolean;
register: any;
handleSubmit: any;
onSubmit: (event: any) => void;
reset: any;
showAlert: boolean;
handleCancel: () => void;
handleConfirm: () => void;
};
const MyModal: React.FC<MyModalProps> = ({
isOpen,
closeModal,
register,
onSubmit,
handleSubmit,
errors,
isDirty,
showAlert,
handleCancel,
handleConfirm,
}) => {
return (
<IonModal isOpen={isOpen}>
<IonHeader>
<IonToolbar>
<IonButton slot="start" onClick={() => closeModal(isDirty)}>
<IonIcon slot="icon-only" name="arrow-back-outline"></IonIcon>
</IonButton>
<IonButton slot="end" type="submit" form="myForm">
<IonLabel>Save</IonLabel>
</IonButton>
</IonToolbar>
</IonHeader>
<IonContent>
<IonCard>
<IonCardContent>
<form onSubmit={handleSubmit(onSubmit)} id="myForm">
<IonItem>
<IonLabel position="floating">Product Name</IonLabel>
<IonInput
type="text"
{...register("name", { required: true })}
></IonInput>
</IonItem>
{errors.name && <span>This field is required</span>}
<IonItem>
<IonLabel position="floating">Amount</IonLabel>
<IonInput
type="number"
{...register("amount")}
></IonInput>
</IonItem>
</form>
</IonCardContent>
</IonCard>
{isDirty && showAlert && (
<UnsavedChangesAlert
isOpen={showAlert}
onCancel={handleCancel}
onConfirm={handleConfirm}
/>
)}
</IonContent>
</IonModal>
);
};
export default MyModal;
import React from "react";
import {
IonPage,
IonHeader,
IonToolbar,
IonTitle,
IonContent,
IonButton,
IonIcon,
IonLabel,
} from "@ionic/react";
import { add } from "ionicons/icons";
import MyModal from "./Modal/MyModal";
import useModalForm from "../../../Hooks/useModalForm";
import useModalHandler from "../../../Hooks/useModalHandler";
const Management: React.FC<any> = () => {
const {
handleSubmit,
register,
onSubmit,
reset,
formState: { errors, isDirty },
} = useModalForm();
const {
isOpen,
showAlert,
openModal,
closeModal,
handleCancel,
handleConfirm,
} = useModalHandler();
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Management</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonButton expand="block" onClick={openModal}>
<IonIcon icon={add} />
<IonLabel>Add Product</IonLabel>
</IonButton>
<MyModal
isOpen={isOpen}
closeModal={closeModal}
register={register}
handleSubmit={handleSubmit}
onSubmit={onSubmit}
errors={errors}
isDirty={isDirty}
reset={reset}
showAlert={showAlert}
handleCancel={handleCancel}
handleConfirm={handleConfirm}
/>
</IonContent>
</IonPage>
);
};
export default Management;
import { IonAlert } from "@ionic/react";
const UnsavedChangesAlert: React.FC<{
isOpen: boolean;
onCancel: () => void;
onConfirm: () => void;
}> = ({ isOpen, onCancel, onConfirm }) => {
return (
<IonAlert
isOpen={isOpen}
header={"Unsaved Changes"}
message={"Are you sure you want to discard unsaved changes?"}
buttons={[
{
text: "Cancel",
role: "cancel",
cssClass: "secondary",
handler: onCancel,
},
{
text: "Unsave Changes",
handler: onConfirm,
},
]}
/>
);
};
export default UnsavedChangesAlert;
import { useForm } from "react-hook-form";
const useModalForm = () => {
const {
register,
handleSubmit,
formState: {
errors,
isDirty
},
reset
} = useForm({
defaultValues: {
name: '',
amount: '',
}});
console.log(isDirty);
const onSubmit = (data: any) => {
console.log(JSON.stringify(data, null, 2));
reset();
};
return {
register,
handleSubmit,
onSubmit,
reset,
formState: {
errors,
isDirty,
}
};
};
export default useModalForm;
import { useState } from "react";
const useModalHandler = () => {
const [isOpen, setIsOpen] = useState(false);
const [showAlert, setShowAlert] = useState(false);
const openModal = () => {
setIsOpen(true);
setShowAlert(false);
};
const closeModal = (isDirty: boolean) => {
if (isDirty) {
setShowAlert(true);
} else {
setIsOpen(false);
}
};
const handleCancel = () => {
setIsOpen(false);
setShowAlert(false);
};
const handleConfirm = () => {
setIsOpen(false);
setShowAlert(false);
};
return {
isOpen,
showAlert,
openModal,
closeModal,
handleCancel,
handleConfirm,
};
};
export default useModalHandler;