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

React多步骤表单axios POST请求必填字段报错问题解决

解决React多步骤表单axios POST提交时的必填字段错误

问题根源

  • 字段命名不匹配:后端返回的错误提示是first_name和last_name必填,但你的表单state里用的是firstName和lastName(驼峰命名),axios提交时会直接把state的key作为参数名传给后端,导致后端无法识别这两个字段,因此判定为未填写。
  • HTML required属性未生效:你给输入框加了required,但当前的Next按钮是自定义的onClick事件切换步骤,并非触发表单的submit事件,而浏览器默认的表单验证只会在submit事件触发时生效,所以这个属性起不到验证作用。

解决方案

1. 统一前后端字段命名

有两种方式处理:

  • 方式一:直接修改state的key为后端期望的下划线命名:
const [formData, setFormData] = useState({
  first_name: "",
  last_name: "",
  email: "",
  password: "",
  password_confirm: "",
});

同时修改输入框的name属性对应:

<input
  type="text"
  name="first_name"
  value={formData.first_name}
  onChange={handleChange}
/>
<!-- lastName同理改成last_name -->
  • 方式二:提交时转换字段名,保持前端驼峰命名:
    在submitData函数里,把formData转换为后端需要的格式:
const submitData = async () => {
  try {
    // 转换字段名适配后端
    const submitPayload = {
      first_name: formData.firstName,
      last_name: formData.lastName,
      email: formData.email,
      password: formData.password,
      password_confirm: formData.password_confirm,
    };
    const response = await axios.post(url, submitPayload);
    console.log(response.data);
  } catch (error) {
    console.error(error);
  }
};

2. 手动验证步骤输入

修改goToNextStep函数,根据当前步骤做字段验证,确保必填字段填写后再跳转:

const goToNextStep = () => {
  // 步骤1验证姓名
  if (currentStep === 1) {
    if (!formData.firstName.trim() || !formData.lastName.trim()) {
      alert("请填写完整姓名");
      return;
    }
  }
  // 步骤2验证邮箱和密码
  if (currentStep === 2) {
    if (!formData.email.trim() || !formData.password.trim() || !formData.password_confirm.trim()) {
      alert("请填写邮箱和密码");
      return;
    }
    // 额外添加密码匹配验证
    if (formData.password !== formData.password_confirm) {
      alert("两次密码输入不一致");
      return;
    }
  }
  setCurrentStep((prevState) => prevState + 1);
};

修改后的完整代码示例

import React, { useState, useEffect } from "react";
import axios from "axios";

const url = "http://34.89.133.245/api/auth/register/";

export function Registr() {
  const [formData, setFormData] = useState({
    firstName: "",
    lastName: "",
    email: "",
    password: "",
    password_confirm: "",
  });
  const [currentStep, setCurrentStep] = useState(1);

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData((prevState) => ({
      ...prevState,
      [name]: value,
    }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
  };

  const goToNextStep = () => {
    // 步骤1验证
    if (currentStep === 1) {
      if (!formData.firstName.trim() || !formData.lastName.trim()) {
        alert("请填写完整姓名");
        return;
      }
    }
    // 步骤2验证
    if (currentStep === 2) {
      if (!formData.email.trim() || !formData.password.trim() || !formData.password_confirm.trim()) {
        alert("请填写邮箱和密码");
        return;
      }
      if (formData.password !== formData.password_confirm) {
        alert("两次密码输入不一致");
        return;
      }
    }
    setCurrentStep((prevState) => prevState + 1);
  };

  const goToPreviousStep = () => {
    setCurrentStep((prevState) => prevState - 1);
  };

  useEffect(() => {
    const submitData = async () => {
      try {
        // 转换字段名适配后端
        const submitPayload = {
          first_name: formData.firstName,
          last_name: formData.lastName,
          email: formData.email,
          password: formData.password,
          password_confirm: formData.password_confirm,
        };
        const response = await axios.post(url, submitPayload);
        console.log(response.data);
      } catch (error) {
        console.error(error);
      }
    };

    if (currentStep === 3) {
      submitData();
    }
  }, [currentStep, formData]);

  const renderStep1 = () => {
    return (
      <div>
        <label>
          First Name:
          <input
            type="text"
            name="firstName"
            value={formData.firstName}
            onChange={handleChange}
          />
        </label>
        <br />
        <label>
          Last Name:
          <input
            type="text"
            name="lastName"
            value={formData.lastName}
            onChange={handleChange}
          />
        </label>
        <br />
        <button onClick={goToNextStep}>Next</button>
      </div>
    );
  };

  const renderStep2 = () => {
    return (
      <div>
        <label>
          Email:
          <input
            type="email"
            name="email"
            value={formData.email}
            onChange={handleChange}
          />
        </label>
        <br />
        <label>
          Password:
          <input
            type="password"
            name="password"
            value={formData.password}
            onChange={handleChange}
          />
        </label>
        <br />
        <br />
        <label>
          Password Confirm:
          <input
            type="password"
            name="password_confirm"
            value={formData.password_confirm}
            onChange={handleChange}
          />
        </label>
        <br />
        <button onClick={goToPreviousStep}>Previous</button>
        <button onClick={goToNextStep}>OK</button>
      </div>
    );
  };

  const renderStep3 = () => {
    return (
      <div>
        <p>Thank you for registering!</p>
      </div>
    );
  };

  return (
    <form onSubmit={handleSubmit}>
      {currentStep === 1 && renderStep1()}
      {currentStep === 2 && renderStep2()}
      {currentStep === 3 && renderStep3()}
    </form>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 16:53:18