React 钩子形式 - 对话框内的字段数组(材料 UI)

Posted

技术标签:

【中文标题】React 钩子形式 - 对话框内的字段数组(材料 UI)【英文标题】:React hook form - Field Array inside Dialog (Material UI) 【发布时间】:2021-03-10 14:01:16 【问题描述】:

所以我有一个表单,其中包含我通过 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 进行正常输入,但它也不起作用。 也可以在没有拖放代码的情况下发生

【问题讨论】:

你想试试shouldUnregister: falseuseForm吗? 【参考方案1】:

正如@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
/>

【讨论】:

您也可以将defaultValues 放在useForm 上。

以上是关于React 钩子形式 - 对话框内的字段数组(材料 UI)的主要内容,如果未能解决你的问题,请参考以下文章

使用反应钩子形式进行条件验证

使用 React 钩子,我如何更新通过道具传递给孩子的对象?

是否可以将 react-datepicker 与反应钩子形式一起使用?

剑道列过滤器内的角度材料日期选择器问题

如果输入在材料 ui 对话框中,react-hook-form 的 setValue 方法不起作用

单击行材料-ui DataGrid内的按钮时如何设置行数据?