如何通过EmailJS传递React购物车的cartItems状态值?
解决方案
问题核心:emailjs.sendForm()只会抓取表单中带name属性的表单控件(input、textarea等)的值,你页面里的购物车列表是普通DOM元素,所以没法被自动收集。下面给两种可行的实现方式:
方法1:用隐藏输入框传递订单数据
在表单里加一个隐藏的input,把格式化后的购物车数据赋值给它,让sendForm()能抓取到:
修改后的组件代码
import React, { useRef } from 'react'; import emailjs from '@emailjs/browser'; import { useCart } from '../../cart-context'; const EmailOrderForm = () => { const { cartItems } = useCart(); const form = useRef(); // 把购物车数据格式化为邮件易读的HTML内容 const formatOrderDetails = () => { return cartItems.map(item => ` <div style="margin: 8px 0; padding-bottom: 8px; border-bottom: 1px solid #eee;"> <p><strong>商品:</strong>${item.name}</p> <p><strong>价格:</strong>${item.price} Kč</p> </div> `).join(''); }; const sendEmail = (e) => { e.preventDefault(); // 给隐藏输入框赋值格式化后的订单数据 const orderInput = form.current.querySelector('[name="order_details"]'); orderInput.value = formatOrderDetails(); emailjs .sendForm( 'service_xxxxx', 'template_xxxxx', form.current, 'XXxxXXxxXXxxXXxx', ) .then( () => console.log('SUCCESS!'), () => console.log('FAILED!'), ); }; return ( <form ref={form} onSubmit={sendEmail}> <label>Name</label> <input type="text" name="user_name" /> <label>Email</label> <input type="email" name="user_email" /> <label>Note</label> <textarea name="message" /> {/* 新增隐藏输入框,用于传递订单数据 */} <input type="hidden" name="order_details" /> <ul> {cartItems.map((item) => ( <li className="cart-item" key={item.index}> <div className="cart-item-image" style={{ backgroundImage: `url(${item.image})`, width: '100px', height: '100px', backgroundSize: 'cover', backgroundPosition: 'center', }} alt={item.name} ></div> <span className="cart-item-name">{item.name}</span> <span className="cart-item-price">{item.price} Kč</span> </li> ))} </ul> <button className="cart-order" type="submit"> Order </button> </form> ); }; export default EmailOrderForm;
EmailJS模板配置
在你的EmailJS模板中添加{{order_details}}变量,并且在模板设置里勾选HTML渲染选项,这样邮件会正确解析格式化后的订单内容。
方法2:使用emailjs.send()直接传递参数(更灵活)
放弃依赖表单的sendForm(),改用send()方法直接构造包含所有数据的对象,不需要依赖表单控件:
修改后的组件代码
import React, { useRef } from 'react'; import emailjs from '@emailjs/browser'; import { useCart } from '../../cart-context'; const EmailOrderForm = () => { const { cartItems } = useCart(); const form = useRef(); // 格式化订单数据 const formatOrderDetails = () => { return cartItems.map(item => ` <div style="margin: 8px 0; padding-bottom: 8px; border-bottom: 1px solid #eee;"> <p><strong>商品:</strong>${item.name}</p> <p><strong>价格:</strong>${item.price} Kč</p> </div> `).join(''); }; const sendEmail = (e) => { e.preventDefault(); // 从表单获取用户输入,再拼接订单数据 const formData = new FormData(form.current); const templateParams = { user_name: formData.get('user_name'), user_email: formData.get('user_email'), message: formData.get('message'), order_details: formatOrderDetails(), }; emailjs .send( 'service_xxxxx', 'template_xxxxx', templateParams, 'XXxxXXxxXXxxXXxx', ) .then( () => console.log('SUCCESS!'), () => console.log('FAILED!'), ); }; return ( <form ref={form} onSubmit={sendEmail}> <label>Name</label> <input type="text" name="user_name" /> <label>Email</label> <input type="email" name="user_email" /> <label>Note</label> <textarea name="message" /> <ul> {cartItems.map((item) => ( <li className="cart-item" key={item.index}> <div className="cart-item-image" style={{ backgroundImage: `url(${item.image})`, width: '100px', height: '100px', backgroundSize: 'cover', backgroundPosition: 'center', }} alt={item.name} ></div> <span className="cart-item-name">{item.name}</span> <span className="cart-item-price">{item.price} Kč</span> </li> ))} </ul> <button className="cart-order" type="submit"> Order </button> </form> ); }; export default EmailOrderForm;
模板配置和方法1一致
在EmailJS模板中添加{{order_details}}变量,开启HTML渲染即可。
额外提示
- 如果不需要HTML格式,把
formatOrderDetails()改成返回纯文本即可,比如用\n分隔商品信息。 - 确保你的EmailJS服务ID、模板ID和公钥配置正确。
内容的提问来源于stack exchange,提问作者katbux
相关产品推荐
相关产品推荐

