[英]Why can't I focus on the current field when using useFieldArray() for dynamic form in react-hook-form?
Using react-hook-form 7.14.2.使用 react-hook-form 7.14.2。 I've got a dynamic form and I'm using the built-in validation.
我有一个动态表单,并且正在使用内置验证。 I'm getting the feeling that react-hook-form can't handle dynamic forms very elegantly, and I should probably just quit churning on this, and fall back to a plain HTML form.
我感觉 react-hook-form 不能非常优雅地处理动态 forms ,我可能应该停止对此进行搅动,并退回到普通的 HTML 形式。
I simply want to focus to stay on the field I'm typing in, after validation occurs.在验证发生后,我只想专注于我正在输入的字段。 The fields are required, but after the validation message shows, and I begin typing, a re-render happens and focus is lost on the current field...and it jumps back to the last field in the form.
这些字段是必需的,但是在显示验证消息并且我开始输入之后,会发生重新渲染并且焦点会丢失在当前字段上......它会跳回到表单中的最后一个字段。 It's a clunky, poor user experience and I just can't seem to find the magic combo of tricks and techniques to get it to work like a normal react-hook-form form would work!
这是一个笨拙、糟糕的用户体验,我似乎无法找到技巧和技术的神奇组合来让它像普通的 react-hook-form 表单一样工作!
Form:形式:
import React, { useEffect } from "react";
import { useForm, useFieldArray } from "react-hook-form";
import { Icon } from "@iconify/react";
import socials from "../../enum/social";
const SocialLinksEdit = props => {
const {
socialLinks,
onSave,
onCancel
} = props;
const { control, register, setValue, setFocus, handleSubmit, formState: { errors } } = useForm();
const { fields, append } = useFieldArray({
control,
name: "socialItems"
});
useEffect(() => {
Object.entries(socials).find(([, s]) => append(s));
}, []);
const getErrorMessage = i => {
if (!errors || Object.keys(errors).length === 0) {
return;
}
if (errors.socialItems && errors.socialItems[i]) {
return errors.socialItems[i].url.message;
}
return null;
};
const SocialItems = () => {
const onFocus = field => {
// setValue(e.target.value);
setFocus(field);
};
const onFocusOut = e => {
setValue(e.target.value);
};
return (
<>
{
fields.map((field, i) => {
let socialData = socialLinks.find(sl => sl.social_service === field.name);
console.log(errors);
return (
<div key={i} className="modal-input-field modal-input-mb">
<div className="modal-label-container">
<label className="modal-label">
<span className="modal-label-icon"><Icon icon={field.icon} /></span>
{field.label}
</label>
</div>
<input
type="text"
// autoFocus={i === 0}
ref={control}
autoFocus
// onFocus={() => onFocus(`socialItems.${i}.url`)}
// onFocusOut={onFocusOut}
{...register(`socialItems.${i}.url`, { required: "URL is required!" })}
defaultValue={socialData?.url}
/>
{errors && <span className="validation">{getErrorMessage(i)}</span>}
</div>
);
})
}
</>
);
};
return (
<div className="modal-container">
<div>
<form onSubmit={handleSubmit(onSave)}>
<div className="modal-title-container">
<div className="modal-title-icon"><Icon icon="bi:megaphone" /></div>
<div className="modal-title">Social Links</div>
</div>
<SocialItems />
<div className="modal-buttons">
<button type="submit" className="form-button-primary">Save</button>
<button type="button" className="form-button-cancel" onClick={e => onCancel(e)}>Cancel</button>
</div>
</form>
</div>
</div>
);
};
export default SocialLinksEdit;
Some 'splainin' to do:一些'splainin'做:
Here's a quick video of how it behaves.这是有关其行为方式的快速视频。 If I could just get the field to retain focus and not skip down to the bottom field like this, I'd be a happy guy.
如果我能让场地保持专注而不是像这样跳到底部场地,我会很开心。
https://www.tiktok.com/@zambizzi/video/7093151720624147755?is_from_webapp=1&sender_device=pc&web_id=7039430208454280710 https://www.tiktok.com/@zambizzi/video/7093151720624147755?is_from_webapp=1&sender_device=pc&web_id=7039430208454280710
Turns out, was just a matter of nesting the fields directly inside, rather than in a separate component, to prevent a re-render:事实证明,只是将字段直接嵌套在内部,而不是在单独的组件中,以防止重新渲染:
return (
<div className="modal-container">
<div>
<form onSubmit={handleSubmit(onSave)}>
<div className="modal-title-container">
<div className="modal-title-icon"><Icon icon="bi:megaphone" /></div>
<div className="modal-title">Social Links</div>
</div>
{
fields.map((field, i) => {
let socialData = socialLinks.find(sl => sl.social_service === field.name);
console.log(errors);
return (
<div key={i} className="modal-input-field modal-input-mb">
<div className="modal-label-container">
<label className="modal-label">
<span className="modal-label-icon"><Icon icon={field.icon} /></span>
{field.label}
</label>
</div>
<div>
<input
type="text"
autoFocus
{...register(`socialItems.${i}.url`, { required: "URL is required!" })}
defaultValue={socialData?.url}
/>
{errors && <span className="validation">{getErrorMessage(i)}</span>}
</div>
</div>
);
})
}
<div className="modal-buttons">
<button type="submit" className="form-button-primary">Save</button>
</div>
</form>
</div>
</div>
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.