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
相关产品推荐
相关产品推荐

