我正在使用 React 18、Ionic 7 和 Formik 2.4.3。当我想滚动到错误位置的顶部时,我使用一个组件
export const getFieldErrorNames = (formikErrors) => {
const transformObjectToDotNotation = (obj, prefix = '', result = []) => {
Object.keys(obj).forEach((key) => {
const value = obj[key]
if (!value) return
const nextKey = prefix ? `${prefix}.${key}` : key
if (typeof value === 'object') {
transformObjectToDotNotation(value, nextKey, result)
} else {
result.push(nextKey)
}
})
return result
}
return transformObjectToDotNotation(formikErrors)
}
const ScrollToFieldError = ({ submitCount, errors }) => {
useEffect(() => {
const fieldErrorNames = getFieldErrorNames(errors)
if (fieldErrorNames.length <= 0) return
const elements = document.getElementsByName(fieldErrorNames[0])
const element = elements[0]
if (!element) return
// Scroll to first known error into view
element.scrollIntoView({ behavior: 'smooth', block: 'center' })
}, [submitCount])
return null
}
export default ScrollToFieldError
在我的 Formik 表单中,我像这样使用组件
const validationSchema = Yup.object().shape({
selectedIds: Yup.array().min(1, 'Select at least one item').required('Select at least one item')
})
...
<Formik
enableReinitialize={true}
initialValues={{ selectedIds }}
validationSchema={validationSchema}
onSubmit={(values) => {
handleSaveAndContinue(values.selectedIds)
}}
>
{(formikProps) => (
<form onSubmit={formikProps.handleSubmit}>
<ScrollToFirstError submitCount={formikProps.submitCount} errors={formikProps.errors} />
{formikProps.touched.selectedIds && formikProps.errors.selectedIds ? (
<div>{formikProps.errors.selectedIds}</div>
) : null}
<IonList>
...
{items.map((item) => (
<IonItem key={item.id}>
<IonCheckbox
name='selectedIds'
value={item.id}
>{`${item.name}`}</IonCheckbox>
</IonItem>
))}
</IonList>
<IonButton aria-lael='Save And COntinue' type='submit'>
Submit
</IonButton>
</form>
)}
</Formik>
问题是,当我单击“提交”按钮而不检查任何内容时,尽管我的错误消息正确显示,但不会滚动到页面顶部。我想让我的组件 ScrollToFirstError 尽可能通用,因为我在其他类型的表单上使用它,所以很好奇是否有一种方法可以调整我现有的表单以使功能正常工作。有问题的示例在这里 - https://stackblitz.com/edit/an5yjh-c2pz8v?file=src%2Fcomponents%2FScrollToFirstError.tsx,src%2Fcomponents%2FMyForm.tsx,package-lock.json
看来
formikProps.submitCount
和formikProps.errors
的值是分别更新的。他们不会同时更新。 ScrollToFieldError
的useEffect仅具有submitCount
的依赖性,而不具有errors
的依赖性。因此,当它检测到提交更改时,错误数组尚未更新。在依赖项中添加 errors
将解决您的问题。
const ScrollToFieldError = ({ submitCount, errors }) => {
useEffect(() => {
const fieldErrorNames = getFieldErrorNames(errors);
if (fieldErrorNames.length <= 0) return;
const elements = document.getElementsByName(fieldErrorNames[0]);
const element = elements[0];
if (!element) return;
// Scroll to first known error into view
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
}, [submitCount, errors]);
return null;
};