繁体   English   中英

如何基于 Ionic React 以 React hook 形式正确更新 isDirty 值

[英]How to properly update isDirty values in react hook form based on Ionic React

我有一个Ionic react上的应用,有两个presentation组件,一个绘制另一个modal,第二个modal,有两个钩子,一个负责打开和关闭modal,第二个负责表单处理逻辑,我需要输入字段时检查表单是否脏,我需要立即更新值 isDirty,因为我想通过管理和 MyModal 将其更改值从 useModalForm 传递到 useModalHandler 挂钩作为“closeModal”function 的参数,因此,当用户开始在字段中输入值时,isDirty 更改为 true,如果我在不保存的情况下关闭表单,则应调用 myAlert 以警告数据丢失。 但实际上 isDirty 并没有改变用户进入该字段时的值,这可能是什么问题?

管理组件

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;

MyModal 组件

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;

useModalForm 钩子

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;

useModalHandler 钩子

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;

UnsavedChangesAlert 组件

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;

使用useForm时,您可以指定一种模式:

mode: onChange | onBlur | onSubmit | onTouched | all

您可以使用onChangeonTouched模式来实现您想要的。 在您的useForm声明中,它看起来像这样:

const {
    handleSubmit, 
    register,
    onSubmit,
    reset,
    formState: { errors, isDirty },
  } = useModalForm({ mode: 'onTouched' });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM