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

ReactJS中如何通过单个处理器获取对应元素的title与price

问题:React中点击Buy按钮获取对应项的title和price属性

我编写了如下React代码,希望点击每个列表项中的Buy按钮时,通过PurchaseHandler获取对应项的obj.title和obj.price属性。尝试使用e.target.value、e.target.id均无效,提示无法读取“title”属性,请问该如何实现?

import { useState } from 'react';
import { Link, Outlet } from 'react-router-dom';
import Cart from './Cart';
import Total from './Total';

const Gallery = () => {
    const [galleryObj, setGalleryObj] = useState([
        {
            id: 1,
            img: "newborn_baby_feet.jpg",
            title: "New Born",
            text: "Register your baby´s first moments and experiences. We provide new born photo sessions for your baby (6 to 15 days of age)",
            bullet1: "Inside, outside and in nature themes",
            bullet2: "Movie themes and much more ideas",
            price: "Cost: $150",
            button: "Contact Us",
            linkPath: "/gallery/1"
        },
        {
            id: 2,
            img: "smashthecake_2.jpg",
            title: "Smash the Cake",
            text: "If you look for photos for your baby birthday we have many smash the cake themes to register this unique moment in your life and your baby´s.",
            bullet1: "Movies, music, cartoon and colorful themes",
            bullet2: "Colorfull photos and videos",
            price: "Cost: $100",
            button: "Contact Us",
            linkPath: "/gallery/2"
        },
        {
            id: 3,
            img: "pregnancy12.jpg",
            title: "Pregnancy",
            text: "If you are pregnant we have gorgeous ideas of pictures and videos to register in poses your pregnancy. Pictures with yourself and your family that will make this time of your life an unforgettable moment.",
            bullet1: "Pictures with yourself and your family",
            bullet2: "Photo editing and inspirational ideas",
            price: "Cost: $200",
            button: "Contact Us",
            linkPath: "/gallery/3"
        },
        {
            id: 4,
            title: "Pre Wedding",
            img: "prewedding_1.jpg",
            text: "If you are going to merry soon, you will want to get this unique moment and keep it forever. Our “pre wedding” use a diversified options of themes for your session.",
            bullet1: "Enjoy the moments before your wedding that will rest forever",
            bullet2: "Reproduce the pre-wedding´s pictures and videos during your wedding party",
            price: "Cost: $250",
            button: "Contact Us",
            linkPath: "/gallery/4"
        },
        {
            id: 5,
            img: "professional_manwithglasses.jpg",
            title: "Professional Profile",
            text: "For those who are preparing for their career, we offer the Professional Profile session.",
            bullet1: "Pictures for your professional LinkedIn profile",
            bullet2: "Hair and looks that best fit your career option",
            price: "Cost: $50",
            button: "Contact Us",
            linkPath: "/gallery/5"
        },
        {
            id: 6,
            img: "family12.jpg",
            title: "Family Session",
            text: "Our team is ready to take that picture of your family with background and colors that will make your family memory endure to the end.",
            bullet1: "Coloring background or outside themes",
            bullet2: "we are ready to make part of this moment in family",
            price: "Cost: $150",
            button: "Contact Us",
            linkPath: "/gallery/6"
        },
        {
            id: 7,
            img: "birthday7.jpg",
            title: "Birthday",
            text: "We also have teenagers 15th birthday sessions for girls and 18th for boys.",
            bullet1: "Nature, classic, pop themes",
            bullet2: "Great image effects, video editing for your birthday",
            price: "Cost: $170",
            button: "Contact Us",
            linkPath: "/gallery/7"
        },
        {
            id: 8,
            img: "social_media_2.jpg",
            title: "Social Media",
            text: "Do you want cool and beautiful pictures for your social medias like Instagram and Facebook?",
            bullet1: "Get a lot of likes from your friends",
            bullet2: "Your social media will never be the same again",
            price: "Cost: $170",
            button: "Contact Us",
            linkPath: "/gallery/8"
        }
    ])

    const [cart, setCart] = useState([]);
    const [total, setTotal] = useState(0); 

    const PurchaseHandler = (e) =>{
        let title = ?;
        let price = ?;
        let totalCart = [...cart];
        let objPurchase = {title, price};
        let totalPrice = total + price;
        totalCart.push(objPurchase);

        setCart(totalCart);
        setTotal(totalPrice);
        console.log(totalCart)
    }
       
    return(
        <div className="gallery-container">
            <h5>SERVICES</h5>
            <h1>Take a Look At The Themes And Sessions We Offer</h1>
                {
                    galleryObj.map((obj)=>{
                        return(
                            <li key={obj.id}>
                                <Link state={obj} to={`/gallery/${obj.id}`}>
                                    <img src={obj.img}/>
                                    <h3>{obj.title}</h3>
                                    <p>{obj.text}</p>
                                    <span>{obj.bullet1}</span>
                                    <span>{obj.bullet2}</span>
                                    <br/>
                                    <span>{obj.price}</span>
                                    <button><Link to="/contact">{obj.button}</Link></button>
                                    <br/>
                                    <button onClick={PurchaseHandler}>Buy</button>
                                </Link>
                            </li>
                        )
                    })
                }
            
            <Outlet context={galleryObj}/>
            <Cart cart={cart}/> 
            <Total total={total}/>
        </div>
    )
}
export default React.memo(Gallery);

解决方案

1. 直接传递当前项的obj给处理函数

在map循环中,每个迭代都能拿到当前项的obj,直接把它作为参数传递给PurchaseHandler即可,不需要通过事件对象获取。

2. 处理价格数值计算

注意obj.price是带描述的字符串(如"Cost: $150"),需要提取其中的纯数值,否则会导致字符串拼接而非数值相加的错误。

修改后的代码

更新PurchaseHandler函数

const PurchaseHandler = (obj) => {
    // 提取价格中的数值部分
    const priceNum = parseFloat(obj.price.replace(/Cost: \$/g, ''));
    const title = obj.title;

    // 使用函数式更新状态,确保依赖最新的状态值
    setCart(prevCart => [...prevCart, { title, price: obj.price }]);
    setTotal(prevTotal => prevTotal + priceNum);
}

修改Buy按钮的onClick事件

<button onClick={() => PurchaseHandler(obj)}>Buy</button>

补充说明

之前用e.target.value或e.target.id无效的原因是:事件对象的target指向的是按钮元素本身,这个元素并没有绑定对应项的title和price属性,自然无法获取到数据。直接传递循环中的obj是最直接可靠的方式,因为它本身就包含了当前项的所有信息。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:54:55