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

Next.js13中Formik表单onSubmit未触发问题求助

问题分析与解决方案

你遇到的问题核心有两个:Form组件使用错误,以及验证Schema拼写错误,导致Formik的提交逻辑被跳过,触发了表单默认的GET提交行为。

具体问题点

  • Form组件来源错误:如果你的<Form>是导入自next/form,它会触发Next.js自带的表单提交(默认GET方法),直接跳转到带查询参数的URL,完全绕过Formik的onSubmit。必须使用Formik提供的Form组件。
  • 验证Schema拼写错误:代码里的validationSchame是拼写错误,正确应为validationSchema,这会导致Yup验证完全失效。

修复步骤

  1. 导入正确的Form组件
    确保从formik库导入Form,而不是next/form:

    import { Formik, Form, Field } from 'formik';
    
  2. 修正Schema拼写
    将validationSchame改为validationSchema:

    <Formik
      validationSchema={validationSchema} // 修正拼写
      initialValues={{
        username: "",
        password: "",
      }}
      onSubmit={async (values, formikHelpers) => {
        console.log(values);
      }}
    >
    
  3. 确保客户端组件环境
    页面顶部的'use client'指令已经正确添加,这部分没问题,Formik只能在客户端组件中运行。

修正后的完整代码示例

'use client';

import { Formik, Form, Field } from 'formik';
import * as Yup from 'yup';
import { Grid, Button } from '@mui/material';
import StyledRedditTextField from './your-styled-component-path'; // 替换为你的组件路径

const validationSchema = Yup.object().shape({
  username: Yup.string().required('用户名不能为空'),
  password: Yup.string().required('密码不能为空'),
});

export default function LoginForm() {
  return (
    <Formik
      validationSchema={validationSchema}
      initialValues={{
        username: "",
        password: "",
      }}
      onSubmit={async (values, formikHelpers) => {
        console.log(values);
        // 这里可以添加你的提交逻辑,比如API请求
        formikHelpers.setSubmitting(false);
      }}
    >
      {({ errors, touched }) => { // 加入touched控制错误提示时机
        return (
          <Form>
            <Grid item sx={{ marginBottom: 1 }}>
              <Field
                sx={{ width: "300px" }}
                name="username"
                as={StyledRedditTextField}
                placeholder="Username"
                label="Username"
                size="medium"
                error={touched.username && Boolean(errors.username)}
                helperText={touched.username && errors.username}
              />
            </Grid>
            <Grid item>
              <Field
                sx={{ width: "300px", marginBottom: 2 }}
                name="password"
                as={StyledRedditTextField}
                placeholder="Password"
                label="Password"
                size="medium"
                type="password"
                error={touched.password && Boolean(errors.password)}
                helperText={touched.password && errors.password}
              />
            </Grid>

            <Grid item>
              <Button
                type="submit"
                variant="contained"
                color="primary"
                sx={{ width: "300px" }}
                size="large"
              >
                Sign In
              </Button>
            </Grid>
          </Form>
        );
      }}
    </Formik>
  );
}

补充说明:加入touched可以让错误提示在用户触碰输入框后才显示,提升用户体验;formikHelpers.setSubmitting(false)用来在异步操作完成后重置提交状态,避免按钮一直处于加载状态。

内容的提问来源于stack exchange,提问作者Eidris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 19:15:34