Sab*_*bin 15 reactjs material-ui react-hook-form
我正在尝试使用自定义Material-UI Autocomplete
组件并将其连接到react-hook-form
.
TLDR:需要使用带有 react-hook-form 控制器的 MUI 自动完成而不需要
defaultValue
我的自定义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} />}
/>
Run Code Online (Sandbox Code Playgroud)
为了使工作与react-hook-form
我设置的setValues
是处理程序onChange
中Autocomplete
,然后手动注册该组件在useEffect
如下
useEffect(() => {
register({ name: "country1" });
},[]);
Run Code Online (Sandbox Code Playgroud)
这工作正常,但我想没有useEffect
钩子,只是直接以某种方式使用寄存器。
接下来我尝试使用Controller
组件 fromreact-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}
/>
Run Code Online (Sandbox Code Playgroud)
我已经onChange
将Autocomplete
组件中的更改为直接返回值,但它似乎不起作用。
inputRef={register}
在 上使用<TextField/>
不会为我削减它,因为我想保存_id
而不是name
HERE是包含两种情况的工作沙箱。第一个 withuseEffect
和setValue
inAutocomplete
是有效的。第二次我尝试使用Controller
组件
任何帮助表示赞赏。
乐
在 Bill 对 MUI Autocomplete 的工作沙箱发表评论后,我设法得到了一个功能结果
<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}
/>
Run Code Online (Sandbox Code Playgroud)
唯一的问题是我MUI Error
在控制台中得到一个
Material-UI:一个组件正在改变要控制的 Autocomplete 的不受控制的值状态。
我试图defaultValue
为它设置一个,但它的行为仍然如此。此外,由于不需要表单中的这些字段,因此我不想从选项数组中设置默认值。
更新的沙箱在这里
任何帮助仍然非常感谢
kri*_*oid 12
接受的答案(可能)适用于自动完成的错误版本。我认为该错误在一段时间后已修复,因此可以稍微简化解决方案。
:与反应钩型和材料的UI时,这是非常有用的参考/ codesandbox 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}
/>
);
}
Run Code Online (Sandbox Code Playgroud)
随着用法:
<ControlledAutocomplete
control={control}
name="inputName"
options={[{ name: 'test' }]}
getOptionLabel={(option) => `Option: ${option.name}`}
renderInput={(params) => <TextField {...params} label="My label" margin="normal" />}
defaultValue={null}
/>
Run Code Online (Sandbox Code Playgroud)
control
是从返回值 useForm(}
请注意,我正在传递null
,defaultValue
因为在我的情况下不需要此输入。如果你离开,defaultValue
你可能会从 material-ui 库中得到一些错误。
更新:
根据评论中的史蒂夫问题,这就是我呈现输入的方式,以便它检查错误:
renderInput={(params) => (
<TextField
{...params}
label="Field Label"
margin="normal"
error={errors[fieldName]}
/>
)}
Run Code Online (Sandbox Code Playgroud)
errors
来自react-hook-form
's的对象在哪里formMethods
:
const { control, watch, errors, handleSubmit } = formMethods
Run Code Online (Sandbox Code Playgroud)
Cli*_*ney 11
所以,我解决了这个问题。但它揭示了我认为自动完成中的错误。
首先...特别是你的问题,您可以消除MUI Error
通过添加默认值的<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>
);
}
Run Code Online (Sandbox Code Playgroud)
ABH*_*IRE 10
import { Button } from "@material-ui/core";
import Autocomplete from "@material-ui/core/Autocomplete";
import { red } from "@material-ui/core/colors";
import Container from "@material-ui/core/Container";
import CssBaseline from "@material-ui/core/CssBaseline";
import { makeStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import AdapterDateFns from "@material-ui/lab/AdapterDateFns";
import LocalizationProvider from "@material-ui/lab/LocalizationProvider";
import React, { useEffect, useState } from "react";
import { Controller, useForm } from "react-hook-form";
export default function App() {
const [itemList, setItemList] = useState([]);
// const classes = useStyles();
const {
control,
handleSubmit,
setValue,
formState: { errors }
} = useForm({
mode: "onChange",
defaultValues: { item: null }
});
const onSubmit = (formInputs) => {
console.log("formInputs", formInputs);
};
useEffect(() => {
setItemList([
{ id: 1, name: "item1" },
{ id: 2, name: "item2" }
]);
setValue("item", { id: 3, name: "item3" });
}, [setValue]);
return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Container component="main" maxWidth="xs">
<CssBaseline />
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<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"}
required
/>
)}
/>
)}
/>
<button
onClick={() => {
setValue("item", { id: 1, name: "item1" });
}}
>
setValue
</button>
<Button
type="submit"
fullWidth
size="large"
variant="contained"
color="primary"
// className={classes.submit}
>
submit
</Button>
</form>
</Container>
</LocalizationProvider>
);
}
Run Code Online (Sandbox Code Playgroud)
我不知道为什么上面的答案对我不起作用,这是对我有用的最简单的代码,我使用withrender
函数根据所选值更改值。Controller
onChange
<Controller\ncontrol={control}\nname="type"\nrules={{\n required: \'Veuillez choisir une r\xc3\xa9ponse\',\n}}\nrender={({ field: { onChange, value } }) => (\n <Autocomplete\n freeSolo\n options={[\'field\', \'select\', \'multiple\', \'date\']}\n onChange={(event, values) => onChange(values)}\n value={value}\n renderInput={(params) => (\n <TextField\n {...params}\n label="type"\n variant="outlined"\n onChange={onChange}\n />\n )}\n />\n)}\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
18507 次 |
最近记录: |