I have a form inside a route, that if there are any validation errors, it should not allow the user to navigate to another route. If there are no validation errors, then allow navigation to another route.
Below is my current code, which the onBlock function does not work does to its async nature as the functions to submit and then validate the form are asynchronous.
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; If a user tries to submit the form without any value in the input, I would expect that onBlock would return false to block navigation. But this does not seem to work. Simply returning false in the onBlock function does however. So it seems that the history.block function does not accept any callbacks. I have also tried to convert it to an async function and await the submitForm & validateForm functions, but still no joy. Is there a way around this? Any help would be greatly appreciated.
Here is CodeSandbox with an example.
https://stackoverflow.com/questions/66529690/using-history-block-with-asynchronous-functions-callback-async-await March 08, 2021 at 08:14PM
没有评论:
发表评论