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

如何在React中将表单数据传递至汇总页并显示购物车总价?

实现建议

1. 先把表单改成受控组件,管理输入状态

你的表单目前都是无控组件,无法获取用户输入的数据,首先要用useState来统一管理所有表单字段的状态:

import React, { useContext, useState } from "react";
import { StoreComponent } from "../../components/StoreComponents";
import { Button } from "@mui/material";
import { useNavigate } from "react-router-dom"; // 导入路由跳转钩子
import "../../styles/Order.css";

function Order() {
  const { getCartTotal } = useContext(StoreComponent);
  const navigate = useNavigate();
  
  // 初始化表单状态,对应所有输入字段
  const [formData, setFormData] = useState({
    firstname: "",
    lastname: "",
    email: "",
    address: "",
    zipcode: "",
    city: "",
    phone: "",
    cardnumber: "",
    expired: "",
    cvc: ""
  });

  // 统一处理输入变化
  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({ ...prev, [name]: value }));
  };

  // 提前计算总价,避免重复调用getCartTotal
  const cartTotal = getCartTotal();
  const finalTotal = cartTotal === 0 ? 0 : cartTotal + 2;

  // 提交表单并跳转到汇总页
  const handleSubmit = (e) => {
    e.preventDefault();
    // 把表单数据和总价通过路由状态传递
    navigate("/summary", {
      state: {
        formData,
        cartTotal,
        finalTotal
      }
    });
  };

  return (
    <form className="place-order" onSubmit={handleSubmit}>
      <div className="place-order-left">
        <p className="title">Delivery information</p>
        <div className="multi-fields">
          <input 
            type="text" 
            placeholder="Firstname" 
            name="firstname" 
            value={formData.firstname} 
            onChange={handleInputChange}
          />
          <input 
            type="text" 
            placeholder="Lastname" 
            name="lastname" 
            value={formData.lastname} 
            onChange={handleInputChange}
          />
        </div>
        <input 
          type="email" 
          placeholder="E-mail" 
          name="email" 
          value={formData.email} 
          onChange={handleInputChange}
        />
        <div className="multi-fields">
          <input 
            type="text" 
            placeholder="Address" 
            name="address" 
            value={formData.address} 
            onChange={handleInputChange}
          />
        </div>
        <div className="multi-fields">
          <input 
            type="text" 
            placeholder="zipcode" 
            name="zipcode" 
            value={formData.zipcode} 
            onChange={handleInputChange}
          />
          <input 
            type="text" 
            placeholder="city" 
            name="city" 
            value={formData.city} 
            onChange={handleInputChange}
          />
        </div>
        <input 
          type="text" 
          placeholder="phone" 
          name="phone" 
          value={formData.phone} 
          onChange={handleInputChange}
        />
      </div>
      <div className="place-order-middle">
        <p className="title">Payment</p>
        <div className="multi-fields">
          <input 
            type="text" 
            placeholder="cardnumber" 
            name="cardnumber" 
            value={formData.cardnumber} 
            onChange={handleInputChange}
          />
        </div>

        <div className="multi-fields">
          <input 
            type="text" 
            placeholder="expired" 
            name="expired" 
            value={formData.expired} 
            onChange={handleInputChange}
          />
          <input 
            type="text" 
            placeholder="CVC-code" 
            name="cvc" 
            value={formData.cvc} 
            onChange={handleInputChange}
          />
        </div>
      </div>

      <div className="place-order-right">
        <div className="cart-total">
          <h2>Cart Total</h2>
          <div>
            <div className="cart-totals-details">
              <p>Sum</p>
              <p>{cartTotal} $</p>
            </div>
            <hr />
            <div className="cart-totals-details">
              <p>Fee</p>
              <p>{cartTotal === 0 ? 0 : 2} $</p>
            </div>
            <hr />
            <div className="cart-totals-details">
              <b>Total</b>
              <b>{finalTotal} $</b>
            </div>
          </div>
          <Button variant="contained" type="submit">Pay now</Button>
        </div>
      </div>
    </form>
  );
}

export default Order;

2. 创建汇总页面,接收并展示数据

新建Summary组件,通过useLocation获取路由传递的状态,渲染用户输入信息和总价:

import React from "react";
import { useLocation } from "react-router-dom";

function Summary() {
  const location = useLocation();
  const { formData, cartTotal, finalTotal } = location.state || {};

  // 防止直接访问汇总页的情况
  if (!formData) {
    return <div>No order data found</div>;
  }

  return (
    <div className="summary-page">
      <h1>Order Summary</h1>
      
      <div className="delivery-info">
        <h2>Delivery Information</h2>
        <p><strong>Name:</strong> {formData.firstname} {formData.lastname}</p>
        <p><strong>Email:</strong> {formData.email}</p>
        <p><strong>Address:</strong> {formData.address}, {formData.city} {formData.zipcode}</p>
        <p><strong>Phone:</strong> {formData.phone}</p>
      </div>

      <div className="payment-info">
        <h2>Payment Details</h2>
        <p><strong>Card Number:</strong> **** **** **** {formData.cardnumber.slice(-4)}</p>
        <p><strong>Expiry:</strong> {formData.expired}</p>
      </div>

      <div className="total-info">
        <h2>Order Total</h2>
        <div className="cart-totals-details">
          <p>Sum</p>
          <p>{cartTotal} $</p>
        </div>
        <hr />
        <div className="cart-totals-details">
          <p>Fee</p>
          <p>{cartTotal === 0 ? 0 : 2} $</p>
        </div>
        <hr />
        <div className="cart-totals-details">
          <b>Total</b>
          <b>{finalTotal} $</b>
        </div>
      </div>
    </div>
  );
}

export default Summary;

3. 额外优化点

  • 全局上下文替代路由传参:如果你的StoreComponent上下文已经用于全局状态管理,也可以把表单数据存入上下文,汇总页直接通过useContext获取,适合需要在多个组件共享订单数据的场景。
  • 表单验证:在handleSubmit中添加必填字段检查,比如姓名、邮箱、地址等,确保用户输入完整后再跳转。
  • 敏感数据处理:银行卡号这类敏感信息不要在前端持久化存储,展示时只显示后四位即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:55:10