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

Next.js 13.4组件执行Server Action后如何清空表单?

解决Next.js 13.4表单提交后清空输入框的问题

你的核心问题在于handleFormSubmit函数的参数错误,导致提交时无法正确使用组件内的formData状态,进而影响清空逻辑。以下是最优修复方案:

问题分析

  1. handleFormSubmit中额外声明的formData参数会覆盖组件内通过useState定义的同名状态变量,导致sendEmail接收到无效值,同时清空操作也无法正确触发表单更新。
  2. 原action属性(Server Actions)无法清空输入框,是因为Server Actions运行在服务端,无法直接控制客户端的非受控表单状态,改用受控组件(绑定value和onChange)是正确的方向。

修复步骤与代码示例

1. 修正表单提交函数参数

移除handleFormSubmit中多余的formData参数,直接使用组件内的状态变量:

const handleFormSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    // 若sendEmail期望接收FormData对象,需将state转换为FormData
    const submitData = new FormData();
    submitData.append('senderEmail', formData.senderEmail);
    submitData.append('message', formData.message);

    const { data, error } = await sendEmail(submitData); // 或直接传formData,取决于sendEmail的参数要求

    if (error) {
        toast.error(error);
    } else {
        toast.success('Email sent successfully!');
        // 清空表单状态
        setFormData({
            senderEmail: '',
            message: '',
        });
    }
};

2. 确保表单与状态双向绑定

你的输入框和文本域已经正确绑定了value和onChange,这部分无需修改,确保每次输入都会更新formData状态。

修复后的完整组件代码

'use client';

import { useSectionInView } from '@/utils/hooks';
import React, { useState } from 'react';
import SectionHeading from '../SectionHeading';
import { motion } from 'framer-motion';
import { fadeIn } from '@/utils/motion';
import SubmitBtn from './SubmitBtn';
import { sendEmail } from '@/utils/sendEmail';
import { toast } from 'react-hot-toast';

interface FormData {
    senderEmail: string;
    message: string;
}

export default function Contact() {
    const { ref } = useSectionInView('Contact');

    const [formData, setFormData] = useState<FormData>({
        senderEmail: '',
        message: '',
    });

    const handleFormSubmit = async (e: React.FormEvent) => {
        e.preventDefault();

        // 转换为FormData(若sendEmail需要此格式)
        const submitData = new FormData();
        submitData.append('senderEmail', formData.senderEmail);
        submitData.append('message', formData.message);

        const { data, error } = await sendEmail(submitData);

        if (error) {
            toast.error(error);
        } else {
            toast.success('Email sent successfully!');
            setFormData({
                senderEmail: '',
                message: '',
            });
        }
    };

    return (
        <motion.section
            className='section_margin w-[min(100%,38rem)] text-center'
            variants={fadeIn('down', 'tween', 0.5, 1.2)}
            initial='hidden'
            whileInView='show'
            ref={ref}
            id='contact'>
            <SectionHeading>Contact me</SectionHeading>
            <p className='text-gray-700 -mt-6 dark:text-white/80'>
                Please contact me directly at{'  '}
                <a className='underline' href='mailto:my@mail.com'>
                    my email
                </a>{' '}
                or through this form.
            </p>

            <form
                className='mt-10 flex flex-col dark:text-black'
                onSubmit={handleFormSubmit}>
                <input
                    type='email'
                    name='senderEmail'
                    className='h-14 px-4 rounded-lg borderBlack dark:bg-white dark:bg-opacity-80 dark:focus:bg-opacity-100 transition-all dark:outline-none'
                    required
                    maxLength={500}
                    placeholder='Your email'
                    value={formData.senderEmail}
                    onChange={(e) => setFormData({ ...formData, senderEmail: e.target.value })}
                />
                <textarea
                    name='message'
                    placeholder='Your message'
                    required
                    maxLength={5000}
                    className='h-52 my-3 rounded-lg borderBlack p-4 dark:bg-white dark:bg-opacity-80 dark:focus:bg-opacity-100 transition-all dark:outline-none'
                    value={formData.message}
                    onChange={(e) => setFormData({ ...formData, message: e.target.value })}
                />
                <SubmitBtn />
            </form>
        </motion.section>
    );
}

额外说明

  • 如果你的sendEmail函数已经支持接收自定义的FormData接口对象(而非浏览器原生的FormData),可以直接传递formData状态变量,无需转换。
  • 受控组件方案是React中处理表单状态的标准方式,能确保表单UI与状态完全同步,避免非受控表单的状态不一致问题。

内容的提问来源于stack exchange,提问作者antonkornilov-ua

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 18:15:09