You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Mantine模态框结合表单状态时的回退问题?

Mantine Form 切换Select选项后值回退问题解决

我使用Mantine UI、Next.js 14和Mantine Forms构建了AddMember组件,尝试用useForm管理表单状态,但切换Select组件的角色选项后点击外部,角色会变回初始值"Admin",不符合预期行为。

组件代码如下:

// All Imports here

const AddMember = ({ id }: { id: string }) => {
 
  const form = useForm<{ email: string; role: Role }>({
    initialValues: {
      role: "Admin",
    },
  });

  async function submitForm(values: { email: string; role: Role }) {
   ...
  }

  const ModalForm = () => {
    return (
      <form
        className="space-y-3"
        onSubmit={form.onSubmit((values) => submitForm(values))}
      >
       
        <Select
          label="Role"
          placeholder="Select the member's role"
          {...form.getInputProps("role")}
          data={[
            { value: "Admin", label: "Admin" },
            { value: "Employee", label: "Employee" },
            { value: "Manager", label: "Manager" },
          ]}
        />

        <Button
          fullWidth
          type="submit"
          onClick={() => {
            //Submit form here
           }
          mt="md"
        >
          Submit
        </Button>
      </form>
    );
  };

  return (
    <Button
      onClick={() => {
        modals.open({
          title: "Add new organisation member",
          children: <ModalForm />,
        });
      }}
    >
      Add Member
    </Button>
  );
};

export default AddMember;

问题原因

核心问题在于ModalForm组件被定义在AddMember内部,每次触发模态框打开或组件重新渲染时,都会重新创建ModalForm实例,导致表单状态与控件的绑定出现异常,失去焦点时状态回退到初始值。另外,initialValues未包含email字段,也可能引发表单状态管理的潜在问题。

解决方法

方案1:将ModalForm移出父组件,通过props传递依赖

把ModalForm抽离到AddMember外部,通过props传入form实例和提交函数,确保组件不会重复创建:

// All Imports here

// 抽离ModalForm组件
const ModalForm = ({ form, submitForm }: { 
  form: ReturnType<typeof useForm>, 
  submitForm: (values: { email: string; role: Role }) => Promise<void> 
}) => {
  return (
    <form
      className="space-y-3"
      onSubmit={form.onSubmit(values => submitForm(values))}
    >
      <Select
        label="Role"
        placeholder="Select the member's role"
        {...form.getInputProps("role")}
        data={[
          { value: "Admin", label: "Admin" },
          { value: "Employee", label: "Employee" },
          { value: "Manager", label: "Manager" },
        ]}
      />

      <Button
        fullWidth
        type="submit"
        mt="md"
      >
        Submit
      </Button>
    </form>
  );
};

const AddMember = ({ id }: { id: string }) => {
  const form = useForm<{ email: string; role: Role }>({
    initialValues: {
      role: "Admin",
      email: "" // 补充email初始值,避免状态异常
    },
  });

  async function submitForm(values: { email: string; role: Role }) {
    // 提交逻辑
  }

  return (
    <Button
      onClick={() => {
        modals.open({
          title: "Add new organisation member",
          children: <ModalForm form={form} submitForm={submitForm} />,
        });
      }}
    >
      Add Member
    </Button>
  );
};

export default AddMember;

方案2:用useMemo包裹表单内容,避免重复渲染

如果不想抽离组件,使用useMemo缓存表单JSX,确保只有依赖变化时才重新创建:

// All Imports here

const AddMember = ({ id }: { id: string }) => {
  const form = useForm<{ email: string; role: Role }>({
    initialValues: {
      role: "Admin",
      email: "" // 补充email初始值
    },
  });

  async function submitForm(values: { email: string; role: Role }) {
    // 提交逻辑
  }

  // 用useMemo缓存表单内容
  const modalFormContent = useMemo(() => (
    <form
      className="space-y-3"
      onSubmit={form.onSubmit(values => submitForm(values))}
    >
      <Select
        label="Role"
        placeholder="Select the member's role"
        {...form.getInputProps("role")}
        data={[
          { value: "Admin", label: "Admin" },
          { value: "Employee", label: "Employee" },
          { value: "Manager", label: "Manager" },
        ]}
      />

      <Button
        fullWidth
        type="submit"
        mt="md"
      >
        Submit
      </Button>
    </form>
  ), [form, submitForm]);

  return (
    <Button
      onClick={() => {
        modals.open({
          title: "Add new organisation member",
          children: modalFormContent,
        });
      }}
    >
      Add Member
    </Button>
  );
};

export default AddMember;

关键注意点

  • 必须为表单所有字段设置初始值,避免useForm状态管理出现异常;
  • 确保表单控件与useForm实例的绑定始终稳定,避免组件重复创建导致的上下文丢失。

内容的提问来源于stack exchange,提问作者Phumu Mahandana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:55:10