如何解决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
相关产品推荐
相关产品推荐

