我一直在从 React Hook 表单的控制器中自定义 Material UI 自动完成,作为更大表单的一部分,但有一些困难。
下拉列表列出了从数据库中提取的建议(props.items,此处表示为对象),如果建议不存在,则可以选择使用下拉列表中的按钮以单独的形式添加新建议。这个“secondComponent”是通过条件渲染打开的。
当它被传递到第二个表单时,数据存储在状态 (heldData) 中,然后通过 React Hook Form 的重置传递回表单,这里为 reset(heldData)。
这完美地更新了表单的值,因为我有一个 onChange 事件,它根据传入的内容设置值。React Hook Form 通过重置处理该逻辑并将完整对象提供给 onChange。
但是,我还想设置 InputValue 以便填充 TextField。
为了在没有选项时创建一个动态按钮('Add ....(input)... as a guest'),我将输入的内容存储为“文本”。我认为我可以使用 OnChange 事件来使用相同的状态来更新 inputValue,如下所示。但是,当我从 onChange 设置文本时,更改不会反映在 inputValue 中。
也许这是因为 useState 是异步的,因此它不会在其他东西完全阻止它之前更新状态。如果是这样,它比我包含的其他代码要简单得多,但不确定。我已经排除了大部分表格(超过 500 行代码),但试图保留任何可能合适的部分。我希望我没有删除任何相关的内容,但如有必要可以更新。
道歉。这是我关于 Stack Overflow 的第一个问题,我对 React(和编码)还很陌生,而且代码可能一团糟。谢谢
**Form**
import React, { useState, useEffect} from "react";
import AutoCompleteSuggestion from "../general/form/AutoCompleteSuggestion";
import SecondComponent from './SecondComponent'
import { useForm } from "react-hook-form";
const items = {
id: 2,
name: "Mr Anderson"
}
const items2 = {
id: 4,
name: "Mr Frog"
}
const defaultValues = {
guest: 'null',
contact: 'null',
}
const AddBooking = () => {
const { handleSubmit, register, control, reset, getValues} = useForm({
defaultValues: defaultValues,
});
const [secondComponent, setSecondComponent] = useState(false);
const [heldData, setHeldData] = useState(null)
const openSecondComponent = (name) => {
setSecondComponent(true)
const data = getValues();
setHeldData(data);
}
useEffect(() => {
!secondComponent.open?
reset(heldData):''
}, [heldData]);
const onSubmit = (data) => {
console.log(data)
};
return (
<>
{!secondComponent.open &&
<form onSubmit={handleSubmit(onSubmit)}
<AutoCompleteSuggestion
control={control}
name="guest"
selection="id"
label="name"
items={items}
openSecondComponent={openSecondComponent}
/>
<AutoCompleteSuggestion
control={control}
name="contact"
selection="id"
label="name"
items={items2}
openSecondComponent={openSecondComponent}
/>
</form>
};
{secondComponent.open?
<SecondComponent/>: ''
};
</>
);
};
这是自定义的自动完成:
**AutoComplete**
import React, { useState } from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete, from "@material-ui/lab/Autocomplete";
import parse from "autosuggest-highlight/parse";
import match from "autosuggest-highlight/match";
import { Controller } from "react-hook-form";
import Button from "@material-ui/core/Button";
const AutoCompleteSuggestion = (props) => {
const [texts, setTexts] = useState('');
return (
<>
<Controller
name={props.name}
control={props.control}
render={({ onChange }) => (
<Autocomplete
options={props.items}
inputValue={texts} //NOT GETTING UPDATED BY STATE
debug={true}
getOptionLabel={(value) => value[props.label]}
noOptionsText = {
<Button onClick={()=> props.opensSecondComponent()}>
Add {texts} as a {props.implementation}
</Button>}
onChange={(e, data) => {
if (data==null){
onChange(null)
} else {
onChange(data[props.selection]); //THIS ONCHANGE WORKS
setTexts(data[props.label]) //THIS DOESN'T UPDATE STATE
}}
renderInput={(params) => (
<TextField
{...params}
onChange = { e=> setTexts(e.target.value)}
/>
)}
renderOption={(option, { inputValue }) => {
const matches = match(option[props.label1, inputValue);
const parts = parse(option[props.label], matches);
return (
<div>
{parts.map((part, index) => (
<span
key={index}
style={{ fontWeight: part.highlight ? 700 : 400 }}
>
{part.text}
</span>
))}
</div>
);
}}
/>
)}
/>
</>
);
};
export default AutoCompleteSuggestion;