我正在尝试使用react-hook-form 的钩子创建一个动态表单useFieldArray。用户应该能够添加或删除字段,从而使其动态化。我查看了本教程以获取灵感,但缺少的部分是如何对状态实现错误验证,这将是一个对象数组:{email: string}[]。(该对象将采用更多键/值对。为了简单起见,我省略了其余部分。)
我尝试过使用yup作为验证模式。它看起来像这样:
const schema = yup.array().of(
yup.object().shape({
email: yup.string().email().required(),
}),
)
Run Code Online (Sandbox Code Playgroud)
React-hook-form 的实现是:
import * as yup from 'yup'
import { yupResolver } from '@hookform/resolvers/yup'
import { useForm, useFieldArray, Controller } from 'react-hook-form'
const { register, control, handleSubmit, errors } = useForm({
resolver: yupResolver(schema),
mode: 'onChange',
})
const { fields, append, remove } = useFieldArray({
control,
name: 'users',
})
Run Code Online (Sandbox Code Playgroud)
该表格或多或少是根据上面链接中的教程进行的。
error当控制台从钩子记录对象时useForm,它始终给出一个空对象{}。看起来好像不起作用。我可能在这里遗漏了一些东西。问题是什么?
我使用 React-hook-form V7 和 Material UI 5 自动完成输入。我在自动完成中的延迟加载值在第一次提交单击时(但在第二次单击时)未验证。怎么了?
useEffect(() => {
setItemList([
{ id: 1, name: "item1" },
{ id: 2, name: "item2" }
]);
setItemIdSelected(2);
}, []);
[...]
<Autocomplete
options={itemList}
getOptionLabel={(item) => (item.name ? item.name : "")}
getOptionSelected={(option, value) =>
value === undefined || value === "" || option.id === value.id
}
value={
itemIdSelected
? itemList.find((item) => item.id === itemIdSelected)
: ""
}
onChange={(event, items) => {
if (items !== null) {
setItemIdSelected(items.id);
}
}}
renderInput={(params) => (
<TextField …Run Code Online (Sandbox Code Playgroud) 我正在使用react-hook-form并使用第三方DatePicker。由于它是一个自定义组件,因此将其用作受控组件来注册它。这很好用
<Controller
control={control}
name="reviewStartDate"
render={({ field: { onChange, onBlur, value } }) => (
<DatePicker
className={`form-control ${errors.reviewStartDate ? 'is-invalid' : ''}`}
customInput={<input />}
wrapperClassName="datePicker"
onChange={onChange}
onBlur={onBlur}
selected={value ? new Date(value) : ''}
dateFormat='dd-MMM-yyyy'
/>
)}
/>
Run Code Online (Sandbox Code Playgroud)
同样/但是,我正在使用第三方Multiselect。这里的值没有被注册。它确实显示了选定的值,但是当我提交表单时,该值不存在于数据中。
<Controller
control={control}
name="rootCauseAnalysisCategory"
render={({ field: { value } }) => (
<Multiselect
options={rootCauseAnalysisCategorys}
isObject={false}
showCheckbox={true}
hidePlaceholder={true}
closeOnSelect={false}
selectedValues={value}
/>
)}
/>
Run Code Online (Sandbox Code Playgroud)
相似地
我想检查 RHF 是否用户已使用参数修改了表单值isDirty。
手动设置默认值是可行的:
const {handleSubmit, control, setValue, setError, setFocus} = useForm({defaultValues: {name: ""}});
Run Code Online (Sandbox Code Playgroud)
这似乎工作正常。
但是,当用户尝试编辑表单时,我将值加载到表单中setValue。
现在我不知道如何以编程方式设置默认值。
如何使用 useEffect() 更改 React-Hook-Form defaultValue?
我就是这样做的,但答案并不正确。值已设置,但 defaultValues 不会以这种方式更改,因此 RHF 无法进行比较。
确保在 useForm 中提供所有输入的默认值,以便钩子表单可以有单一的事实来源来比较表单是否脏。
https://react-hook-form.com/api/useform/formstate
如何动态设置 defaultValues 以便它甚至可以在“编辑”模式下工作?
我正在使用 useFieldArray 从后端 api 获取默认值。我的类别是一个字符串数组。但是,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 }
)
Run Code Online (Sandbox Code Playgroud)
因此,我必须从前端修改我的表单,如下所示:
type FormData = {
title: string
description: …Run Code Online (Sandbox Code Playgroud) 如何使用react-testing-library对屏蔽的输入字段进行单元测试。该组件是使用material ui 和react-hook-form 开发的。在这里您可以找到代码并处理我这边的示例。提前致谢
测试文件:
let Phone_Input = getByTestId("phone-input");
fireEvent.change(
<InputMask mask="(999) 999-9999">{() => Phone_Input}</InputMask>,
{
target: { value: "9500902621" }
}
);
Run Code Online (Sandbox Code Playgroud)
成分:
<InputMask mask="(999) 999-9999">
{() => (
<TextField
id="standard-required"
name="phone"
label="phone"
placeholder="Enter Phone"
inputProps={{
"data-testid": "phone-input"
}}
/>
)}
</InputMask>
Run Code Online (Sandbox Code Playgroud)
错误:
The given element does not have a value setter
expect(received).toBe(expected) // Object.is equality
Expected: "(950) 090-2621"
Received: "(___) ___-____"
Run Code Online (Sandbox Code Playgroud) reactjs jestjs material-ui react-testing-library react-hook-form
const roles = [\n { value: "STAFF", label: "Staff" },\n { value: "ADMIN", label: "Administrator" },\n { value: "MANAG", label: "Manager" },\n { value: "SUPER", label: "Supervisor" },\n { value: "OTHER", label: "Other" }\n]\n\n<Controller as={<TextField />} className={classes.textField} select label="Select Role" \nname="role" variant="outlined" required control={control} fullWidth inputRef={register({ \nrequired: true })}>\n {roles.map(role => (\n <MenuItem key={role.value} value={role.value}>\n {role.label}\n </MenuItem>\n ))}\n name="role"\n</Controller>\nRun Code Online (Sandbox Code Playgroud)\n我获取下拉列表的值 {node: input, value: "MANAG", focus: \xc6\x92}\nERROR: Field ismissing nameattribute:\nMISSING THE NAME ATTRIBUTE OF "role" 如何分配角色名称属性?
我正在尝试使用materialui select 的react hook 表单控制器来找出onChange 事件,但我无法弄清楚当select 更改以调用handleChange 事件时如何触发该事件。我创建了一个沙箱来复制,我也有单独的问题Warning: findDOMNode is deprecated in StrictMode我无法理解如何使用 createRef 来阻止这个问题,但主要问题是 onChange 事件,因为我需要根据 Select 渲染不同的进一步 TextFields -价值。
https://codesandbox.io/s/react-hook-form-select-onchange-uiic6
<form onSubmit={handleSubmit(onSubmit)}>
<Grid container direction="column" spacing={2}>
<Grid item>
<FormControl fullWidth variant="outlined" className={classes.formControl}>
<InputLabel id="demo-simple-select-label">Folder Name</InputLabel>
<Controller
control={control}
name="folderSelect"
onChange={handleChange}
defaultValue=""
render={({onChange, value, onBlur, name}) => (
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
onChange={onChange}
value={value ? value : ''}
name={name}>
<MenuItem value="Invoices" key="Invoices">
Invoices
</MenuItem>
<MenuItem value="Statements" key="Statements">
Statements
</MenuItem>
<MenuItem value="Credits" key="Credits">
Credits
</MenuItem>
</Select>
)}
/>
</FormControl>
</Grid> …Run Code Online (Sandbox Code Playgroud) 我在 onChange 模式下使用react-hook-form。我根据验证状态启用/禁用提交按钮。它工作得很好。
现在我必须切换到 onBlur 模式。当前的解决方案不再按预期工作。当所有字段都有效时,我希望提交按钮立即启用。现在只有当我单击最后一个字段时它才启用。我应该在代码中更改哪些内容才能按预期工作?
const { register, errors, handleSubmit, formState } = useForm({
mode: "onChange" // I want to change it to onBlur
});
const { isValid } = formState;
...
<input disabled={!isValid} type="submit" />
Run Code Online (Sandbox Code Playgroud)
这是一个示例:https://codesandbox.io/s/react-hook-form-disable-submit-button-onblur-0293x ?file=/src/index.js
更新解决方案: NearHuscarl 的回答有助于找到解决方案。我必须停留在 onChange 模式并自己处理错误消息的显示。仅当该字段位于 formState 的 TouchFields 对象中时,我才显示错误。
const form = useForm({
mode: "onChange" // I want to change it to onBlur
});
const { register, handleSubmit, formState } = form;
const { isValid, touchedFields, errors } = formState; …Run Code Online (Sandbox Code Playgroud) 我正在开发一个 Ionic React 应用程序,我想使用 React Hook Form 和 Yup Resolvers 来提交表单。我的表单包含一个单选按钮和其他两个输入。
我在使用单选按钮时遇到困难。我应该如何编写它才能存储它的值并提交?下面你可以找到我的组件。即使我选择其中一个单选按钮,也不会存储任何值。
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
const validationSchema = yup.object().shape({
firstName: yup.string().required("First name is required"),
lastName: yup.string().required("Last name is required"),
});
const AddUser = () => {
const history = useHistory();
const [type, seType] = useState("");
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const {
register,
handleSubmit,
formState: { errors },
getValues,
} = useForm({
mode: "onChange",
resolver: yupResolver(validationSchema), …Run Code Online (Sandbox Code Playgroud) react-hook-form ×10
reactjs ×9
material-ui ×3
javascript ×2
yup ×2
controller ×1
forms ×1
jestjs ×1
menuitem ×1
onchange ×1
react-hooks ×1
typescript ×1
validation ×1