通过React Router Link传递useFormik提交数据遇两大问题求解决
解决Formik表单数据传递与验证跳转问题
问题1:首次提交传递空state的解决
原因:useState的更新是异步的,点击提交时setData(values)执行后,data不会立即更新,此时Link携带的还是旧的空对象。
解决方案:无需额外维护data状态,直接在Formik的onSubmit回调中,通过useNavigate传递表单值,规避异步更新的延迟问题。
问题2:跳过验证直接跳转的解决
原因:Link的点击优先级高于表单submit事件,点击按钮时直接触发跳转,绕过了Formik的验证流程。
解决方案:移除Link,使用react-router-dom的useNavigate钩子,仅在Formik验证通过(进入onSubmit回调)后执行页面跳转。
修改后的Home组件代码
import React from "react"; import { Stack, Paper, TextField, Button } from "@mui/material"; import { useFormik } from "formik"; import * as yup from "yup"; import { useNavigate } from "react-router-dom"; const validationSchema = yup.object({ location: yup.string("Enter Location").required("Location is required"), adults: yup.number("Enter number of Adults").required("Adult is required"), currency: yup.string("Enter Currency").required("Currency is required"), }); const Home = () => { const navigate = useNavigate(); const formik = useFormik({ initialValues: { location: "", adults: "", children: "", infants: "", pets: "", currency: "", }, validationSchema: validationSchema, onSubmit: (values) => { // 验证通过后跳转并传递表单数据 navigate("/result", { state: { data: values } }); console.log(JSON.stringify(values, null, 2)); }, }); return ( <Stack> <Paper elevation={3} sx={{ maxWidth: 700, height: 500, p: 2 }}> <form onSubmit={formik.handleSubmit}> <TextField name="location" value={formik.values.location} onChange={formik.handleChange} id="outlined-basic" label="Location" variant="outlined" error={formik.touched.location && Boolean(formik.errors.location)} helperText={formik.touched.location && formik.errors.location} fullWidth sx={{ m: 1 }} /> <TextField name="adults" value={formik.values.adults} onChange={formik.handleChange} type="number" id="outlined-basic" label="Adults" variant="outlined" error={formik.touched.adults && Boolean(formik.errors.adults)} helperText={formik.touched.adults && formik.errors.adults} fullWidth sx={{ m: 1 }} /> <TextField name="children" value={formik.values.children} onChange={formik.handleChange} type="number" id="outlined-basic" label="Children" variant="outlined" fullWidth sx={{ m: 1 }} /> <TextField name="infants" value={formik.values.infants} onChange={formik.handleChange} type="number" id="outlined-basic" label="Infants" variant="outlined" fullWidth sx={{ m: 1 }} /> <TextField name="pets" value={formik.values.pets} onChange={formik.handleChange} type="number" id="outlined-basic" label="Pets" variant="outlined" fullWidth sx={{ m: 1 }} /> <TextField name="currency" value={formik.values.currency} onChange={formik.handleChange} id="outlined-basic" label="Currency" variant="outlined" error={formik.touched.currency && Boolean(formik.errors.currency)} helperText={formik.touched.currency && formik.errors.currency} fullWidth sx={{ m: 1 }} /> {/* 移除内部Link,直接触发表单提交 */} <Button type="submit" variant="contained" sx={{ m: 1 }}> Submit </Button> </form> </Paper> </Stack> ); }; export default Home;
优化后的Result组件代码(可选,用于展示数据)
import React from 'react'; import { useLocation } from 'react-router-dom'; const Result = () => { const location = useLocation(); const formData = location.state?.data || {}; return ( <div style={{ padding: '2rem' }}> <h1>Form Submission Result</h1> <div style={{ marginTop: '1rem' }}> <p><strong>Location:</strong> {formData.location}</p> <p><strong>Adults:</strong> {formData.adults}</p> <p><strong>Children:</strong> {formData.children || 0}</p> <p><strong>Infants:</strong> {formData.infants || 0}</p> <p><strong>Pets:</strong> {formData.pets || 0}</p> <p><strong>Currency:</strong> {formData.currency}</p> </div> </div> ) } export default Result
内容的提问来源于stack exchange,提问作者Haider Abbas Abidi
相关产品推荐
相关产品推荐

