我正在使用 useFieldArray 从后端 api 获取默认值。我的 categories 是一个字符串数组。但是,react-hook-form 仅支持对象数组。这是我的猫鼬的架构
type BookDocument = Document & {
title: string
description: string
categories: string[]
language: string
publicationYear: number
}
const bookSchema = new Schema(
{
title: { type: String, required: true },
description: { type: String, required: true },
categories: [{ type: String, requried: true }],
language: { type: String, required: true },
publicationYear: { type: Number, required: true },
},
{ timestamps: true }
)
因此,从前端我必须修改我的表单如下:
type FormData = {
title: string
description: string
categories: { category: string }[]
language: string
year: number
}
const {
handleSubmit,
control,
formState: { errors },
} = useForm<FormData>({
mode: 'onBlur',
defaultValues: {
title: book.title ?? '',
description: book.description ?? '',
categories:
book.categories.map((elem) => {
return { category: elem }
}) ?? '',
language: book.language ?? '',
year: book.publicationYear ?? '',
},
})
您可以调用已解构为 const 的
handleSubmit
函数(位于代码片段中的 control
上方)。您可以选择在何处调用 handleSubmit
- 可能在表单上的按钮上 - 并且您可以调用回调,而不是仅仅调用 handleSubmit
,如下所示:
const handleFormSubmission = (data: any) => {
handleSubmit(wrappedSubmit)(data);
};
有一个办法。查看我用来欺骗它返回平面数组的代码:
import {
Box,
Button,
Grid,
InputLabel,
TextField,
Typography,
} from '@mui/material';
import React from 'react';
import { Controller, useFieldArray, useFormContext } from 'react-hook-form';
import InputErrorMessages from '../../../shared/InputErrorMessages';
export default function Variables() {
const {
control,
formState: {
errors,
},
} = useFormContext();
const { fields, append, remove } = useFieldArray({
name: 'variables',
control,
});
return(
<Grid item xs={12}>
<Typography variant="h6">Variables</Typography>
<Box my={2}>
<InputErrorMessages name="variables" errors={errors} />
</Box>
<Grid container spacing={2}>
{ fields.map((unused, index) => (
<Grid item key={index} xs={12}>
<Controller
name={`variables.${index}`}
control={control}
render={({ field }) => (
<>
<InputLabel id="size">{`CRV${index+1} =`}</InputLabel>
<TextField
onChange={field.onChange}
onBlur={field.onBlur}
inputRef={field.ref}
name={`variables.${index}.value`}
value={field.value.value || field.value}
sx={{ width: '100%' }}
/>
</>)}
/>
</Grid>
))}
<Grid item>
<Button onClick={() => append('value')}>Add Variable</Button>
</Grid>
<Grid item>
{ fields.length > 0 && (<Button onClick={() => remove(fields.length - 1)}>Delete Variable</Button>)}
</Grid>
</Grid>
</Grid>
)
}
我欺骗了它,但没有使用
field
中的fields.map
项目。相反,我使用 Controller 注册了自己的控件,因为我想控制字段的名称及其值。 IE。我想将该字段命名为 variables.${index}
而不是 variables.${index}.value
;如果您使用 useFieldArray() 返回的 field
项,后者将是自动的。
当你点击handleSubmit时,你会看到
variable
是一个平面数组。
但是,有一个小问题。如果您从后端加载带有字段的表单,它将期望
variable
是具有 value
属性的对象数组;它无法理解扁平的字符串数组。
但是,我再次能够欺骗它,因为我控制了该值。由此可见:
value={field.value.value || field.value}
基本上,如果对象上没有
value
属性,那么它一定是一个字符串;那么只需使用字符串即可。
希望这有帮助!