我试图使用react-hook-form来验证输入。但是我发现,如果将输入放置在Material UI的对话框组件中,则react-hook-form的setValue
不能按预期工作,但是当我删除对话框组件时它可以工作。我想这是因为该值是在组件安装之前设置的,但仍然找不到解决方案。
将从服务器中检索该值,所以我不能使用react-hook-form的defaultValues
。
https://codesandbox.io/s/react-hook-form-material-ui-twbbw
我尝试使用useState
来控制输入值,但是还有另一个问题。清除输入后,单击“提交”按钮,并显示错误消息,我输入的第一个字母将不会显示。
答案 0 :(得分:1)
由于setValue
具有其特殊性(如上@ Domino987所述),因此对于其中表单填充有从服务器获取的数据的方案,一种替代方案是:
useState
保留获取的值; Controller
的{{1}}来设置值和; 一个伪示例:
defaultValue
答案 1 :(得分:0)
用于外部受控组件
如果您使用的是V3,我建议您使用react-hook-form-input
https://github.com/react-hook-form/react-hook-form-input
import React from 'react';
import useForm from 'react-hook-form';
import { RHFInput } from 'react-hook-form-input';
import Select from 'react-select';
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
];
function App() {
const { handleSubmit, register, setValue, reset } = useForm();
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
<RHFInput
as={<Select options={options} />}
rules={{ required: true }}
name="reactSelect"
register={register}
setValue={setValue}
/>
<button type="button">Reset Form</button>
<button>submit</button>
</form>
);
}
如果您使用的是V4,我建议您使用Controller
https://react-hook-form.com/api/#Controller
import React from 'react';
import Select from 'react-select';
import { TextField } from "@material-ui/core";
import { useForm, Controller } from 'react-hook-form';
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
];
function App() {
const { handleSubmit, control } = useForm();
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
<Controller
as={<Select options={options} />}
control={control}
rules={{ required: true }}
onChange={([selected]) => {
// React Select return object instead of value for selection
return { value: selected };
}}
name="reactSelect"
/>
<Controller
as={<TextField />}
name="firstName"
control={control}
/>
<button>submit</button>
</form>
);
}
包裹受控组件并收集数据的想法仍然可以隔离外部受控组件内部的重新渲染。
答案 2 :(得分:0)
问题出在寄存器功能上。您将在调用Textfield的引用之后使用注册功能注册Textfield。
在初始渲染之后,将使用setValue
调用useEffect将名称设置为123。如果open
为true,则在useEffect之后呈现对话框内容。
呈现内容之后,将调用带有寄存器的ref,并将Textfield的默认值(此处为undefined
设置为name的值。
这就是为什么显示文本字段的值为“”的原因。您需要在调用render和ref回调之后调用setValue,以使该值保持不变。
您有两种选择可以做到这一点:
setTimeout
后,在useEffect中使用异步延迟(open
或promise)设置async值。因此,如果将open
添加到useEffect依赖数组并设置值async,它将起作用。这是Sandbox。useForm({defaultValues: {name: '123}})
将默认值添加到钩子中。答案 3 :(得分:0)
带有受控输入的 react-hook-form,是的验证,材料 UI 组件,setValue
import React from 'react';
import {useForm, Controller} from 'react-hook-form';
import {yupResolver} from '@hookform/resolvers/yup';
import Autocomplete from '@material-ui/lab/Autocomplete';
import { TextField } from '@material-ui/core';
import * as yup from 'yup';
const schema = yup.object().shape({
firstname: yup.string().required(),
buyer: yup.string().required(),
});
const UserForm = () => {
const {
watch,
setValue,
register,
handleSubmit,
control,
formState: {errors},
} = useForm({
defaultValues: {
item: {"id":2,"name":"item2"},
},
resolver: yupResolver(schema),
});
const itemList = [
{id: 1, name: 'item1'},
{id: 2, name: 'item2'},
];
return (
<div
style={{
margin: '200px',
}}>
<form onSubmit={handleSubmit(d => console.table(d))}>
<Controller
control={control}
name="item"
rules={{required: true}}
render={({field: {onChange, value}}) => (
<Autocomplete
onChange={(event, item) => {
onChange(item);
}}
value={value}
options={itemList}
getOptionLabel={item => (item.name ? item.name : '')}
getOptionSelected={(option, value) =>
value === undefined || value === '' || option.id === value.id
}
renderInput={params => (
<TextField
{...params}
label="items"
margin="normal"
variant="outlined"
error={!!errors.item}
helperText={errors.item && 'item required'}
/>
)}
/>
)}
/>
<input type="submit" />
<button
onClick={() => {
setValue('item', {id: 2, name: 'item2'});
}}>
setValue
</button>
<h6>data from register</h6>
{<pre>{JSON.stringify(watch())}</pre>}
</form>
</div>
);
};
export default UserForm;