我正在尝试使用自定义的Material-UI Autocomplete
组件并将其连接到react-hook-form
。
TLDR:需要在没有
defaultValue
的情况下将MUI自动完成与react-hook-form控制器一起使用
我的自定义Autocomplete
组件采用结构为{_id:'', name: ''}
的对象,它显示名称并在选择选项时返回_id
。 Autocomplete
可以正常工作。
<Autocomplete
options={options}
getOptionLabel={option => option.name}
getOptionSelected={(option, value) => option._id === value._id}
onChange={(event, newValue, reason) => {
handler(name, reason === 'clear' ? null : newValue._id);
}}
renderInput={params => <TextField {...params} {...inputProps} />}
/>
为了使其与react-hook-form
一起使用,我在setValues
中将onChange
设置为Autocomplete
的处理程序,并在{ {1}}如下
useEffect
这很好用,但是我不希望使用useEffect(() => {
register({ name: "country1" });
},[]);
钩子,而直接以某种方式使用寄存器。
接下来,我尝试使用useEffect
中的Controller
组件来正确注册表单中的字段,而不使用react-hook-form
钩子
useEffect
我已经更改了<Controller
name="country2"
as={
<Autocomplete
options={options}
getOptionLabel={option => option.name}
getOptionSelected={(option, value) => option._id === value._id}
onChange={(event, newValue, reason) =>
reason === "clear" ? null : newValue._id
}
renderInput={params => (
<TextField {...params} label="Country" />
)}
/>
}
control={control}
/>
组件中的onChange
以直接返回该值,但是它似乎不起作用。
在Autocomplete
上使用inputRef={register}
不会对我有用,因为我要保存<TextField/>
而不是_id
HERE是具有这两种情况的有效沙箱。第一个在name
中具有useEffect
和setValue
的作品。我第二次尝试使用Autocomplete
组件
感谢您的帮助。
LE
在Bill通过MUI自动完成功能的工作沙箱发表评论后,我设法获得了有效的结果
Controller
唯一的问题是我在控制台中得到了<Controller
name="country"
as={
<Autocomplete
options={options}
getOptionLabel={option => option.name}
getOptionSelected={(option, value) => option._id === value._id}
renderInput={params => <TextField {...params} label="Country" />}
/>
}
onChange={([, { _id }]) => _id}
control={control}
/>
Material-UI:某个组件正在更改要控制的自动完成的不受控制的值状态。
我尝试为其设置一个MUI Error
,但它的行为仍然如此。另外,由于不需要表单中的这些字段,因此我也不想从options数组中设置默认值。
更新后的沙盒HERE
仍然非常感谢任何帮助
答案 0 :(得分:5)
所以,我解决了这个问题。但这揭示了我认为是自动完成功能中的错误。
首先...专门针对您的问题,您可以通过向MUI Error
添加 defaultValue 来消除<Controller>
。但这仅仅是另一轮或问题的开始。
问题是getOptionLabel
,getOptionSelected
和onChange
的函数有时会传递值(在这种情况下为_id
),有时会传递选项结构-正如您所期望的。
这是我最后想出的代码:
import React from "react";
import { useForm, Controller } from "react-hook-form";
import { TextField } from "@material-ui/core";
import { Autocomplete } from "@material-ui/lab";
import { Button } from "@material-ui/core";
export default function FormTwo({ options }) {
const { register, handleSubmit, control } = useForm();
const getOpObj = option => {
if (!option._id) option = options.find(op => op._id === option);
return option;
};
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
<Controller
name="country"
as={
<Autocomplete
options={options}
getOptionLabel={option => getOpObj(option).name}
getOptionSelected={(option, value) => {
return option._id === getOpObj(value)._id;
}}
renderInput={params => <TextField {...params} label="Country" />}
/>
}
onChange={([, obj]) => getOpObj(obj)._id}
control={control}
defaultValue={options[0]}
/>
<Button type="submit">Submit</Button>
</form>
);
}
答案 1 :(得分:4)
接受的答案(可能)适用于错误版本的自动完成。我认为此错误已在一段时间后修复,因此可以稍微简化解决方案。
当使用react-hook-form和material-ui:https://codesandbox.io/s/react-hook-form-controller-601-j2df5?
时,这是非常有用的参考/代码框。在上面的链接中,我修改了自动完成示例:
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
const ControlledAutocomplete = ({ options = [], renderInput, getOptionLabel, onChange: ignored, control, defaultValue, name, renderOption }) => {
return (
<Controller
render={({ onChange, ...props }) => (
<Autocomplete
options={options}
getOptionLabel={getOptionLabel}
renderOption={renderOption}
renderInput={renderInput}
onChange={(e, data) => onChange(data)}
{...props}
/>
)}
onChange={([, data]) => data}
defaultValue={defaultValue}
name={name}
control={control}
/>
);
}
用法:
<ControlledAutocomplete
control={control}
name="inputName"
options={[{ name: 'test' }]}
getOptionLabel={(option) => `Option: ${option.name}`}
renderInput={(params) => <TextField {...params} label="My label" margin="normal" />}
defaultValue={null}
/>
control
来自useForm(}
的返回值
请注意,我将null
传递为defaultValue
,因为在我的情况下,此输入不是必需的。如果您离开defaultValue
,可能会从material-ui库中得到一些错误。
答案 2 :(得分:-1)
不使用控制器,借助 register、useForm 的 setValue 和 value、Autocomplete 的 onChange 可以达到相同的效果。
const [selectedCaste, setSelectedCaste] = useState([]);
const {register, errors, setValue} = useForm();
useEffect(() => {
register("caste");
}, [register]);
return (
<Autocomplete
multiple
options={casteList}
disableCloseOnSelect
value={selectedCaste}
onChange={(_, values) => {
setSelectedCaste([...values]);
setValue("caste", [...values]);
}}
getOptionLabel={(option) => option}
renderOption={(option, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option}
</React.Fragment>
)}
style={{ width: "100%" }}
renderInput={(params) => (
<TextField
{...params}
id="caste"
error={!!errors.caste}
helperText={errors.caste?.message}
variant="outlined"
label="Select caste"
placeholder="Caste"
/>
)}
/>
);