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

React+EmailJS表单提交后总价无法重置的问题求助

问题描述
  • 基于EmailJS开发表单,需求为点击发送按钮后重置表单:复选框取消选中,总价恢复为$0.00
  • 当前异常:点击按钮后复选框已取消选中,但总价无法重置为$0.00
  • 技术栈:Tailwind、@emailjs/browser、Vite
  • 调试情况:总价输入框存在于e.target中,但调用e.target.reset()无法重置它
import { useState } from 'react';
// EmailJS
import EmailJS from '@emailjs/browser';

const App = () => {
  // EmailJS
  const sendEmail = (e) => {
    e.preventDefault();

    EmailJS.sendForm(
      'YOUR_SERVICE_ID', // Please put your service ID if you have Email JS.
      'YOUR_TEMPLATE_ID', // Please put your template ID if you have Email JS.
      e.target,
      'YOUR_PUBLIC_KEY' // Please put your key if you have Email JS.
    ).then(
      (result) => {
        console.log(result.text);
      },
      (error) => {
        console.log(error.text);
      }
    );
    e.target.reset();
  };

  // Checkbox
  const list = [
    {
      name: 'A',
      price: 50,
    },
    {
      name: 'B',
      price: 50,
    },
  ];

  const [checked, setChecked] = useState(new Array(list.length).fill(false));
  const [total, setTotal] = useState(0);

  const toggle = (place) => {
    const updatedChecked = checked.map((item, index) => {
      if (index === place) {
        return !item;
      } else {
        return item;
      }
    });

    setChecked(updatedChecked);

    const initialValue = 0;
    const totalPrice = updatedChecked.reduce((acc, currentTorF, index) => {
      if (currentTorF === true) {
        return acc + list[index].price;
      }
      return acc;
    }, initialValue);

    setTotal(totalPrice);
  };

  const getTotalPrice = (price) => {
    return `$${price.toFixed(2)} `;
  };

  // JSX
  return (
    <>
      <div className='flex mx-36'>
        <div className='flex-1'>
          <form onSubmit={sendEmail} required>
            <fieldset className='border border-solid rounded border-gray-300 p-3'>
              <legend className='p-1'>Choice</legend>

              <ul>
                {list.map(({ name, price }, index) => {
                  return (
                    <li key={index} className='flex justify-between'>
                      <div className='p-1'>
                        <input
                          type='checkbox'
                          checked={checked[index]}
                          onChange={() => toggle(index)}
                          id={`linked-${index}`}
                          name='services'
                          value={name}
                        />
                        <label htmlFor={`linked-${index}`} className='p-1'>
                          {name}
                        </label>
                      </div>
                      <div>{getTotalPrice(price)}</div>
                    </li>
                  );
                })}
              </ul>
            </fieldset>

            <fieldset className='flex justify-between p-8'>
              <label htmlFor='total'>Price</label>
              <input
                type='text'
                name='total'
                value={getTotalPrice(total)}
                className='w-16 border-none outline-none'
                readOnly
              />
            </fieldset>

            {/* Send button */}
            <button
              className='table mx-auto border border-gray-300 rounded mt-4 px-6 py-1'
              type='submit'
            >
              Send
            </button>
          </form>
        </div>
      </div>
    </>
  );
};

export default App;
解决方案

问题本质

总价输入框是受控组件,它的显示值完全由React状态total驱动,e.target.reset()只能重置原生DOM表单元素的默认值,无法修改React状态,因此总价不会自动更新。同时你的复选框也是受控组件,当前视觉上的取消选中只是DOM临时状态,React状态checked并未同步更新,后续可能出现状态不一致问题。

修改方案

在邮件发送流程结束后(无论成功或失败),手动重置React状态,同步更新受控组件:

修改后的sendEmail函数

const sendEmail = (e) => {
  e.preventDefault();

  EmailJS.sendForm(
    'YOUR_SERVICE_ID',
    'YOUR_TEMPLATE_ID',
    e.target,
    'YOUR_PUBLIC_KEY'
  ).then(
    (result) => {
      console.log(result.text);
    },
    (error) => {
      console.log(error.text);
    }
  ).finally(() => {
    // 重置原生表单DOM
    e.target.reset();
    // 重置React状态,同步更新受控组件
    setChecked(new Array(list.length).fill(false));
    setTotal(0);
  });
};

说明

  • 使用finally块确保邮件发送成功或失败后,都会执行重置逻辑,和你原本的需求匹配
  • 手动重置checked和total状态后,受控的复选框和总价输入框会自动同步更新,彻底解决状态不一致问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:10:25