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

React-Router-Dom v6多页面数据传递(首页→产品页→结算页)方案问询

React Router v6 页面间商品数据传递实现方案

需求说明

在React项目中,通过API在首页获取商品数据,需实现以下数据传递:

  • 点击首页商品卡片的「Add to cart」按钮时,将当前商品的image、name、price、description传递到Product页面
  • 将该商品数据从Product页面传递到Checkout页面

实现步骤

1. 首页(Homepage.js):传递商品数据到Product页面

修改商品卡片的「Add to cart」按钮点击事件,利用navigate方法的第二个参数state携带目标商品数据:

// Homepage.js 中按钮部分修改
<button 
  type="button" 
  onClick={() => {
    navigate('/products', {
      state: {
        image: item.image,
        name: item.name,
        price: item.price,
        description: item.description
      }
    })
  }} 
  className="btn btn-warning"
>
  Add to cart
</button>

2. Product页面:接收数据并传递到Checkout页面

通过useLocation钩子接收首页传递的商品数据,同时修改页面内的「Add to cart」按钮,将数据继续传递到Checkout页面:

// Product.js 修改后的完整核心代码
import axios from 'axios'
import { useEffect, useState } from "react";
import { useLocation, useNavigate } from 'react-router-dom'
import img1 from '../images/beigehoodie.jpg'

const Product = () => {
    const CONFIG_OBJ = {
        headers: {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + localStorage.getItem("token")
        }
    }
    const [allreview, setAllReview] = useState([])
    const location = useLocation()
    const navigate = useNavigate()
    
    // 解构接收商品数据,添加默认值避免空数据报错
    const { image, name, price, description } = location.state || {}

    const getReview = async () => {
        const response = await axios.get(`http://localhost:4000/getreview`, CONFIG_OBJ);
        if (response.status === 200) {
            setAllReview(response.data.review);
        } else {
            console.log("Error loading items")
        }
    }

    useEffect(() => {
        getReview()
    }, []);

    return (
        <div className="container login-container">
            <div className="row d-flex">
                <div className="col-md-7 col-sm-12 ">
                    {/* 使用传递的商品图片,默认值为本地图片 */}
                    <img src={image || img1} className="instagram" width='400px' height='400px' />
                </div>
        
                <div className="col-md-5 col-sm-12 ">
                    <div className="card shadow">
                        <div className='col-md-12 text-center'>
                            <div className="card">
                                <div className="card-header">
                                    {/* 展示商品名称 */}
                                    <h5>{name || '商品名称'}</h5>
                                </div>
                                <ul className="list-group list-group-flush">
                                    <li className="list-group-item">Rating</li>
                                    {/* 展示商品价格 */}
                                    <li className="list-group-item">{price || '0'}</li>
                                    {/* 展示商品描述 */}
                                    <li className="list-group-item">{description || '暂无描述'}</li>
                                    {/* 点击按钮传递数据到Checkout页面 */}
                                    <button 
                                        onClick={() => {
                                            navigate('/checkout', {
                                                state: { image, name, price, description }
                                            })
                                        }}
                                        className="btn btn-warning"
                                    >
                                        Add to cart
                                    </button>
                                </ul>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            
            {/* 以下为原有评论、评论表单部分,保持不变 */}
            <h2>Reviews</h2>
            <div>
            {allreview.map((review) => {
                return (
                    <div key={review._id}>
                        <span className="border border-warning-subtle">
                            <table className="table">
                                <tbody>
                                    <tr>
                                        <th>Name</th>
                                        <td>{review.customer.fullName}</td>
                                    </tr>
                                    <tr>
                                        <th>Rating</th>
                                        <td>{review.star}</td>
                                    </tr>
                                    <tr>
                                        <th>Review</th>
                                        <td>{review.reviewText}</td>
                                    </tr>
                                </tbody>
                            </table>
                        </span>
                    </div>    
                )
            })}
            </div>
            <h2>Write a review</h2>
            <p>Ratings</p>
            <select className="form-select" aria-label="Default select example">
                <option selected>Select</option>
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
            </select>

            <form>
                <div className="mb-3">
                    <label for="exampleInputEmail1" className="form-label">Write review</label>
                    <input type="text" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"/>
                </div>
            </form>
            <button className="btn btn-warning">Submit</button>
        </div>
    )
}

export default Product 

3. Checkout页面:接收并使用商品数据

通过useLocation钩子接收Product页面传递的商品数据,用于订单摘要展示:

// Checkout.js 修改后的完整核心代码
import axios from 'axios'
import { useEffect, useState } from "react";
import { useLocation } from 'react-router-dom'

const Checkout = () => {
    const CONFIG_OBJ = {
        headers: {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + localStorage.getItem("token")
        }
    }

    const [alladdress, setAllAddress] = useState([])
    const location = useLocation()
    // 解构接收商品数据
    const { name, price } = location.state || {}

    const getAddress = async () => {
        const response = await axios.get(`http://localhost:4000/getaddress`, CONFIG_OBJ);
        if (response.status === 200) {
            setAllAddress(response.data.address);
        } else {
            console.log("Error loading items")
        }
    }

    useEffect(() => {
        getAddress()
    }, []);

    // 计算订单总价
    const totalPrice = price ? parseInt(price) + 10 : 0

    return (
        <div className="container login-container">
            <div className="row">
                <div className="col-md-8 col-sm-12 justify-content-left" >
                    {alladdress.map((add) => {
                        return (
                            <div key={add._id}>
                                <div className="card" >
                                    <div className="card-body justify-content-left">
                                        <h5 className="card-title">Shipping</h5>
                                        <h6 className="card-subtitle mb-2 text-body-secondary">Name: {add.fullName}</h6>
                                        <p className="card-text">Address: {add.address},{add.city},{add.postalcode},{add.country}</p>
                                        <a href="#" className="card-link">Edit</a>
                                    </div>
                                </div>
                            </div>
                        )
                    })}

                    <div className="card" >
                        <div className="card-body">
                            <h5 className="card-title">Payment</h5>
                            <h6 className="card-subtitle mb-2 text-body-secondary">Card subtitle</h6>
                            <p className="card-text">Method- Paypal</p>
                            <a href="#" className="card-link">Edit</a>
                        </div>
                    </div>
                </div>

                <div className="col-md-4 col-sm-12 ">
                    <div className="card shadow">
                        <div className='col-md-12 text-center'>
                            <div className="card">
                                <div className="card-header">
                                    <h2>Order Summary</h2>
                                </div>
                                <table className="table">
                                    <tbody>
                                        <tr>
                                            <th>Item</th>
                                            <td>{name || '未选择商品'}</td>
                                        </tr>
                                        <tr>
                                            <th>Price</th>
                                            <td>{price || '0'}</td>
                                        </tr>
                                        <tr>
                                            <th>Shipping</th>
                                            <td>$0</td>
                                        </tr>
                                        <tr>
                                            <th>Tax</th>
                                            <td>$10</td>
                                        </tr>
                                        <tr>
                                            <th>Total</th>
                                            <td>{totalPrice}</td>
                                        </tr>
                                    </tbody>
                                </table>
                                <a href="#" className="btn btn-warning">Place order</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}

export default Checkout

关键说明

  • React Router v6中,页面跳转传递数据的标准方式是使用useNavigate的state参数,数据会被存储在浏览器的历史记录中
  • 接收数据使用useLocation钩子,从location.state中获取内容,需添加默认值避免页面刷新时state为空导致的报错
  • 该方案无需依赖额外状态管理库,适合简单的页面间数据传递场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 13:58:10