You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:44:56