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

NextJS+TypeScript下Nodemailer组件contact.tsx状态错误修复求助

NextJS + TypeScript 联系表单组件修复方案

核心问题梳理

  • form状态类型不匹配:初始值为字符串'',后续赋值为对象,违反TypeScript类型约束
  • lname输入框value绑定错误:错误绑定到inputs.fname,导致输入 lastName 时显示 firstName 的值
  • 提交校验引用不存在字段:判断条件中inputs.phone未定义,组件内无对应输入框,导致校验逻辑失效

修复后的完整代码

import React, { useState } from 'react';

// 定义表单状态的类型
type FormState = {
  state: 'idle' | 'loading' | 'error' | 'success';
  message?: string;
};

// 定义输入字段的类型
type Inputs = {
  fname: string;
  lname: string;
  email: string;
  message: string;
};

export default function Contact() {
  const [inputs, setInputs] = useState<Inputs>({
    fname: '',
    lname: '',
    email: '',
    message: ''
  });

  // 初始化form状态为idle,符合类型定义
  const [form, setForm] = useState<FormState>({ state: 'idle' });

  // 给事件参数添加明确类型
  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    setInputs((prev) => ({
      ...prev,
      [e.target.id]: e.target.value,
    }));
  };

  const onSubmitForm = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    // 移除不存在的phone校验,保留现有字段的校验
    if (inputs.fname && inputs.lname && inputs.email && inputs.message) {
      setForm({ state: 'loading' });
      try {
        const res = await fetch(`/api/contact`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(inputs),
        });

        const { error } = await res.json();

        if (error) {
          setForm({
            state: 'error',
            message: error,
          });
          return;
        }

        setForm({
          state: 'success',
          message: 'Your message was sent successfully.',
        });
        // 重置输入字段
        setInputs({
          fname: '',
          lname: '',
          email: '',
          message: '',
        });
      } catch (error) {
        setForm({
          state: 'error',
          message: 'Something went wrong',
        });
      }
    }
  };

  return (
    <form onSubmit={onSubmitForm}>
      <input
        type="text"
        id="fname"
        value={inputs.fname}
        onChange={handleChange}
        className="form-control"
        placeholder="First Name"
        required
      />

      <input
        type="text"
        id="lname"
        value={inputs.lname} {/* 修复value绑定错误 */}
        onChange={handleChange}
        className="form-control"
        placeholder="Last Name"
        required
      />

      <input
        type="email"
        id="email"
        value={inputs.email}
        onChange={handleChange}
        className="form-control"
        placeholder="Email"
        required
      />

      <textarea
        id="message"
        value={inputs.message}
        onChange={handleChange}
        rows={4}
        className="form-control"
        placeholder="Messages"
        required
      ></textarea>

      <button
        type="submit"
        className="button"
      >
        Send inquiry
      </button>

      {/* 根据form状态展示对应提示 */}
      {form.state === 'loading' && <div>Sending....</div>}
      {form.state === 'error' && <div>{form.message}</div>}
      {form.state === 'success' && <div>Sent successfully</div>}
    </form>
  );
}

修复细节说明

  1. 类型定义规范

    • 新增FormState和Inputs类型,明确状态结构和输入字段类型,解决TypeScript类型不匹配问题
    • 给useState显式指定类型,提升代码可读性和类型安全性
  2. 修复输入框绑定错误

    • 将lname输入框的value属性从inputs.fname改为inputs.lname,确保输入值与状态同步
  3. 修正提交校验逻辑

    • 移除判断条件中的inputs.phone,因为组件内未添加该输入框,避免校验逻辑错误
  4. 完善事件参数类型

    • 给handleChange和onSubmitForm的事件参数添加TypeScript类型,符合React事件类型规范

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:54:54