React 钩子形式 - 对话框内的字段数组 (Material UI)
React hook form - Field Array inside Dialog (Material UI)
所以我有一个表单,其中包含我通过来自 react-hook-form 的字段数组添加的自定义字段。
一切正常,但我为 属性 项添加了拖放(以重新排序),现在直接显示所有这些字段会很麻烦,所以我将它们移动到对话框中。
这些图片让您了解什么更容易拖放...(正确的)
问题是字段数组值在模式关闭后“重置”(在我在编辑模式中键入这些表单值之后),我想这与重新渲染有关,但我不确定。
我试图在此处展示没有 d&d 和其他无用内容的最小代码示例...
但这里是 codesandbox playground 和完整的代码
CreateCategoryForm.js
const defaultValues = {
name: "",
slug: "",
description: "",
properties: [] // field array
}
function CreateCategoryForm() {
const methods = useForm({ defaultValues });
const { handleSubmit, control, errors } = methods;
const { fields, append, remove, swap } = useFieldArray({ name: "properties", control });
const onSubmit = async (data) => {
console.log("data: ", data);
};
return (
<Container>
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<FormTextField name="name" />
<FormTextField name="slug" />
<FormTextField name="description" />
{fields.map((card, idx) => (
<PropertyCard key={card.id} card={card} idx={idx} errors={errors} remove={remove} />
))}
<Button onClick={() => append({ name: "", label: "", type: "text", filterable: true })}>
Add Property
</Button>
<FormSubmitButton>
Create Category
</FormSubmitButton>
</form>
</FormProvider>
</Container>
);
}
PropertyCard.js
function PropertyCard({ card, errors, idx, remove }) {
const [dialogOpen, setDialogOpen] = React.useState(false);
const handleOpenDialog = () => {
setDialogOpen(true);
};
const handleCloseDialog = () => {
setDialogOpen(false);
};
return (
<div>
Property {idx + 1}
<IconButton onClick={() => handleOpenDialog()}>
edit
</IconButton>
<IconButton onClick={() => remove(idx)}>
X
</IconButton>
<Dialog
fullScreen
open={dialogOpen}
onClose={handleCloseDialog}
>
<Container maxWidth="xs">
<FormTextField
name={`properties[${idx}].name`}
label="Property Name"
/>
<FormTextField
name={`properties[${idx}].label`}
label="Property Label"
/>
<FormSelect
name={`properties[${idx}].type`}
label="Filter Type"
options={[
{ label: "text", value: "text" },
{ label: "bool", value: "bool" }
]}
defaultValue="text"
/>
<FormSwitch
name={`properties[${idx}].filterable`}
label="Filterable"
defaultValue={true}
/>
<IconButton onClick={handleCloseDialog}>
X
</IconButton>
</Container>
</Dialog>
</div>
);
}
- 问题不是 FormProvider 上下文或我的 FormTextField 组件...我尝试使用 ref 进行正常输入,但它也不起作用。
- 在没有拖放代码的情况下也会发生
正如@Bill 在评论中提到的那样,shouldUnregister: false
似乎可以解决问题。
所以我将 useForm 更改为:
const methods = useForm({ defaultValues, shouldUnregister: false });
并且对于每个 属性 输入,我都添加了 defautlValue 以使其工作。
<FormTextField
name={`properties[${idx}].name`}
label="Property Name"
defaultValue={getValues()?.properties?.[idx]?.name} // added this
/>
<FormTextField
name={`properties[${idx}].label`}
label="Property Label"
defaultValue={getValues()?.properties?.[idx]?.label} // added this
/>
<FormSelect
name={`properties[${idx}].type`}
label="Filter Type"
options={[
{ label: "text", value: "text" },
{ label: "bool", value: "bool" }
]}
defaultValue={getValues()?.properties?.[idx]?.type || 'text'} // added this
/>
所以我有一个表单,其中包含我通过来自 react-hook-form 的字段数组添加的自定义字段。 一切正常,但我为 属性 项添加了拖放(以重新排序),现在直接显示所有这些字段会很麻烦,所以我将它们移动到对话框中。
这些图片让您了解什么更容易拖放...(正确的)
问题是字段数组值在模式关闭后“重置”(在我在编辑模式中键入这些表单值之后),我想这与重新渲染有关,但我不确定。
我试图在此处展示没有 d&d 和其他无用内容的最小代码示例...
但这里是 codesandbox playground 和完整的代码
CreateCategoryForm.js
const defaultValues = {
name: "",
slug: "",
description: "",
properties: [] // field array
}
function CreateCategoryForm() {
const methods = useForm({ defaultValues });
const { handleSubmit, control, errors } = methods;
const { fields, append, remove, swap } = useFieldArray({ name: "properties", control });
const onSubmit = async (data) => {
console.log("data: ", data);
};
return (
<Container>
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<FormTextField name="name" />
<FormTextField name="slug" />
<FormTextField name="description" />
{fields.map((card, idx) => (
<PropertyCard key={card.id} card={card} idx={idx} errors={errors} remove={remove} />
))}
<Button onClick={() => append({ name: "", label: "", type: "text", filterable: true })}>
Add Property
</Button>
<FormSubmitButton>
Create Category
</FormSubmitButton>
</form>
</FormProvider>
</Container>
);
}
PropertyCard.js
function PropertyCard({ card, errors, idx, remove }) {
const [dialogOpen, setDialogOpen] = React.useState(false);
const handleOpenDialog = () => {
setDialogOpen(true);
};
const handleCloseDialog = () => {
setDialogOpen(false);
};
return (
<div>
Property {idx + 1}
<IconButton onClick={() => handleOpenDialog()}>
edit
</IconButton>
<IconButton onClick={() => remove(idx)}>
X
</IconButton>
<Dialog
fullScreen
open={dialogOpen}
onClose={handleCloseDialog}
>
<Container maxWidth="xs">
<FormTextField
name={`properties[${idx}].name`}
label="Property Name"
/>
<FormTextField
name={`properties[${idx}].label`}
label="Property Label"
/>
<FormSelect
name={`properties[${idx}].type`}
label="Filter Type"
options={[
{ label: "text", value: "text" },
{ label: "bool", value: "bool" }
]}
defaultValue="text"
/>
<FormSwitch
name={`properties[${idx}].filterable`}
label="Filterable"
defaultValue={true}
/>
<IconButton onClick={handleCloseDialog}>
X
</IconButton>
</Container>
</Dialog>
</div>
);
}
- 问题不是 FormProvider 上下文或我的 FormTextField 组件...我尝试使用 ref 进行正常输入,但它也不起作用。
- 在没有拖放代码的情况下也会发生
正如@Bill 在评论中提到的那样,shouldUnregister: false
似乎可以解决问题。
所以我将 useForm 更改为:
const methods = useForm({ defaultValues, shouldUnregister: false });
并且对于每个 属性 输入,我都添加了 defautlValue 以使其工作。
<FormTextField
name={`properties[${idx}].name`}
label="Property Name"
defaultValue={getValues()?.properties?.[idx]?.name} // added this
/>
<FormTextField
name={`properties[${idx}].label`}
label="Property Label"
defaultValue={getValues()?.properties?.[idx]?.label} // added this
/>
<FormSelect
name={`properties[${idx}].type`}
label="Filter Type"
options={[
{ label: "text", value: "text" },
{ label: "bool", value: "bool" }
]}
defaultValue={getValues()?.properties?.[idx]?.type || 'text'} // added this
/>