[英]mui autocomplete with react-hook-form: defaultValue in formData
[英]MUI Autocomplete and react-hook-form not displaying selected option with fetched data
我在来自反应钩子表单的表单中有一个 MUI 自动完成功能,它在填写表单时工作正常,但是当我想显示填充了获取数据的表单时,MUI 自动完成功能仅在两次渲染后显示所选选项。
我认为这与 useEffect 和重置(来自反应挂钩形式)有关,因为选项为 static 的自动完成功能工作正常,但我还必须从我的 API 获取选项的自动完成功能仅在第二次运行 useEffect 后才能正常工作。
我无法重现 codesandbox,因为它是一个消耗真实 api 的大型项目,但如果需要,我可以提供更多信息。 如果有人可以帮助我,请提前致谢。
我选择要在表单内可视化的项目的页面:
const People: React.FC = () => {
const [show, setShow] = useState(false);
const [modalData, setModalData] = useState<PeopleProps>({} as PeopleProps);
async function showCustomer(id: string) {
await api
.get(`people/${id}`)
.then((response) => {
setModalData(response.data);
setShow(true);
})
.catch((error) => toast.error('Error')
)
}
return (
<>
{...} // there's a table here with items that onClick will fire showCustomer()
<Modal
data={modalData}
visible={show}
/>
</>
);
};
我在模态中的形式:
const Modal: React.FC<ModalProps> = ({data, visible}) => {
const [situations, setSituations] = useState<Options[]>([]);
const methods = useForm<PeopleProps>({defaultValues: data});
const {reset} = methods;
/* FETCH POSSIBLE SITUATIONS FROM API*/
useEffect(() => {
api
.get('situations')
.then((situation) => setSituations(situation.data.data))
.catch((error) => toast.error('Error'));
}, [visible]);
/* RESET FORM TO POPULATE WITH FETCHED DATA */
useEffect(() => reset(data), [visible]);
return (
<Dialog open={visible}>
<FormProvider {...methods}>
<DialogContent>
<ComboBox
name="situation_id"
label="Situação"
options={situations.map((item) => ({
id: item.id,
text: item.description
}))}
/>
</DialogContent>
</FormProvider>
</Dialog>
);
};
export default Modal;
ComboBox 组件:
const ComboBox: React.FC<ComboProps> = ({name, options, ...props}) => {
const {control, getValues} = useFormContext();
return (
<Controller
name={`${name}`}
control={control}
render={(props) => (
<Autocomplete
{...props}
options={options}
getOptionLabel={(option) => option.text}
getOptionSelected={(option, value) => option.id === value.id}
defaultValue={options.find(
(item) => item.id === getValues(`${name}`)
)}
renderInput={(params) => (
<TextField
variant="outlined"
{...props}
{...params}
/>
)}
onChange={(event, data) => {
props.field.onChange(data?.id);
}}
/>
)}
/>
);
};
export default ComboBox;
我认为你在这里简化了一些事情:
<Modal />
组件,这样您就不必在不使用它时渲染它。<Autocomplete />
组件设置默认值,因为 RHF 会为你管理defaultValue
。 因此,如果您正在重置表单,RHF 将使用该控件的新值。<Autocomplete />
的当前/默认值要容易得多 - 因此每次发生更改时都不会迭代所有选项(并将 situation_id 作为此控件的值传递) ,只需在获取情况后找到默认选项并使用此值重置表单即可。 在 CodeSandbox 中,我将您的控件从“situation_id”重命名为“situation”。 这样你只需要 map "situation_id" 在<Modal />
的第一次渲染上,就在你将编辑的值发送到你的 api 之前保存。我做了一个小的 CodeSandbox 试图重现你的用例,看看:
mui@v4
mui@v5
另一件重要的事情:只有当你有深度嵌套的控件时,你才应该使用useFormContext
,否则只需将控件传递给你的<ComboBox />
组件。 与使用FormProvider
一样,如果表单变得更大和更复杂,它可能会影响应用程序的性能。 从文档中:
React Hook Form 的 FormProvider 建立在 React 的 Context API 之上。它解决了数据通过组件树传递的问题,而无需在每一层都手动传递 props。 这也会导致组件树在 React Hook Form 触发 state 更新时触发重新渲染
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.