我有一个表单在一个路由里面,如果存在任何验证错误,它不应该允许用户导航到另一个路由。如果没有验证错误,则允许导航到另一个路由。
以下是我的当前代码,onBlock
函数由于其异步性质而无法工作,因为提交和验证表单的函数都是异步的。
FormComponent.js
import React, { useState, useEffect, useRef } from "react";
import { FieldArray } from "formik";
import { useHistory } from "react-router-dom";
import * as Yup from "yup";
import Form from "./Form";
import TextInput from "./TextInput";
const FormComponent = () => {
const history = useHistory();
const [initialValues, setInitialValues] = useState();
const [isSubmitted, setIsSubmitted] = useState(false);
const block = useRef();
const formRef = useRef(null);
const onFormSubmit = async (values) => {
setIsSubmitted(true);
};
const validationSchema = () => {
const schema = {
test: Yup.string().required("Input is Required")
};
return Yup.object(schema);
};
const onBlock = () => {
const { submitForm, validateForm } = formRef?.current || {};
// submit form first
submitForm()
.then(() => {
// then validate form
validateForm()
.then(() => {
// if form is valid - should navigate to route
// if form is not valid - should remain on current route
return formRef?.current.isValid;
})
.catch(() => false);
})
.catch(() => false);
};
const redirectToPage = () => {
history.push("/other-page");
};
useEffect(() => {
block.current = history.block(onBlock);
return () => {
block.current && block.current();
};
});
useEffect(() => {
if (isSubmitted) redirectToPage();
}, [isSubmitted]);
useEffect(() => {
setInitialValues({
test: ""
});
}, []);
return initialValues ? (
<Form
initialValues={initialValues}
onSubmit={onFormSubmit}
formRef={formRef}
validationSchema={validationSchema}
>
<FieldArray
name="formDetails"
render={(arrayHelpers) =>
arrayHelpers && arrayHelpers.form && arrayHelpers.form.values
? (() => {
const { form } = arrayHelpers;
formRef.current = form;
return (
<>
<TextInput name="test" />
<button type="submit">Submit</button>
</>
);
})()
: null
}
/>
</Form>
) : null;
};
export default FormComponent;
如果用户在输入框中没有输入任何值就尝试提交表单,我期望当
onBlock
返回 false
时会阻止导航。但是这似乎不起作用。只有在 onBlock
函数中直接返回 false
才有效。因此看起来 history.block
函数不接受任何回调函数。我还尝试将其转换为 async
函数,并使用 await
等待 submitForm
和 validateForm
函数,但仍然不能解决问题。是否有什么方法可以绕过此问题?非常感谢您的帮助。这里有一个带有示例的CodeSandbox。
isValid
值最初为true
,因此如果您在不编辑表单的情况下转到另一个路由,它将允许导航,尽管没有填写表单。这就是我想避免的。 - mcclosasubmitCount
添加到逻辑中即可。 - Jonathan PortorrealvalidateOnMount={true}
属性。 - Jonathan Portorreal