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

React卡片组件Discard按钮点击事件失效问题求助

React Card组件状态切换问题修复

问题描述

开发了一个包含active、selected、discarded、complete四种状态的React Card组件,状态切换规则如下:

  • 默认状态为active;
  • 点击卡片任意区域切换为selected,显示Back和Discard按钮;
  • 点击Back按钮切换回active;
  • 点击Discard按钮切换为discarded。

状态存储在App组件层级,通过props向Card组件传递SelectCard和DiscardCard两个状态更新函数。目前SelectCard可正常实现active与selected的切换,但点击Discard按钮无法触发DiscardCard函数,怀疑是按钮位于带onClick事件的div内导致事件冲突。

核心问题与修复方案

问题根源

  1. 函数未执行:Card组件的按钮点击事件中仅引用了props.onPress和props.onDiscard,未添加()执行函数,导致点击时无响应;
  2. 事件冒泡冲突:按钮点击事件会向上冒泡触发父div的onClick事件,干扰状态切换逻辑;
  3. 条件判断错误:Back按钮的判断条件误用了props.item.selected,而数据结构中实际使用state字段存储状态。

修复步骤

  1. 在按钮的onClick回调中执行函数:将props.onPress改为props.onPress(),props.onDiscard改为props.onDiscard();
  2. 调用event.stopPropagation()阻止事件冒泡,避免触发父元素的点击事件;
  3. 修正Back按钮的判断逻辑,基于props.item.state === 'selected'处理点击事件。

修改后的代码

App.js(逻辑保持不变)

import { useState } from 'react'
import reactLogo from './assets/react.svg'
import Card from './components/Card'
import data from "./assets/data.json"
import {nanoid} from "nanoid"

function App() {
  const [people, setPeople] = useState(data['people'].map(
    el=>{
      return {
        ...el,
        'key' : nanoid(),
      }
    }
  ))

  const [myCard, setMyCard] = useState(
    {
      "name":"Name and Surname",
      "img":"https://i.picsum.photos/id/1070/200/300.jpg?hmac=dJNTYlLwT_0RupxbJNbw5Wj-q2cCTB4Xh-GqWRofIIc",
      "description": "This is a silly descriptionhis is a silly descriptionhis is a silly description",
      'key' : nanoid(),
      "selected":false,
      "active":true,
    }
  )


  function SelectCard(CardKey){
    console.log('SelectCard')
    setPeople(oldPeople=>{
      return oldPeople.map(el=>{

        return el.key === CardKey
                ? { ...el, 'state': el.state === 'active'?'selected': 'active'}
                : { ...el, 'state':'active'}
          })
    })
  }

  function DiscardCard(CardKey){
    console.log('DiscardCard')
    setPeople(oldPeople=>{
      return oldPeople.map(el=>{
        return el.key === CardKey
                ? { ...el, 'state': el.state === 'discarded'?'active': 'discarded'}
                : { ...el}
          })
    })
  }

  const cards = people.map(el=>{
    return <Card 
            key = {el.key} 
            item={el} 
            onPress={()=>SelectCard(el.key)}
            onDiscard={()=>DiscardCard(el.key)}
          />
  })

  
  return (
    <div className="App">
      <div className='container'>
        <div className='left'>
          <div className='cards'>
            {cards}
          </div>
        </div>
        <div className = 'right'>
          <h4>You are: </h4>
          <Card key = {myCard.key} item={myCard}/>
        </div>
     </div>
     
    </div>
  )
}

export default App

Card.js(关键修改)

import { useState } from 'react'

function Card(props) {
  function getClassName(state) {
    switch (state) {
      case "active":
        return "";
      case "selected":
        return "overlay-selected";
      case "discarded":
        return "overlay-discarded";
      case "complete":
        return "overlay-complete";
      default:
        return "";
    }
  }

  const className = `card ${getClassName(props.item.state)}`

  return (
    <div 
        className={className} 
        onClick={() => props.onPress()}>
        <img className='card-img' alt='Card Image' src={props.item.img} />
        <h3 className='card-title'>{props.item.name} </h3>
        { props.item.state === 'selected' ? 
        
            <div className='card-cta'>
                <button 
                    className='btn btn-back'
                    onClick={(event) => {
                        event.stopPropagation();
                        props.onPress();
                    }}
                >Back</button>
                <button 
                    className='btn btn-discard'
                    onClick={(event) => {
                        event.stopPropagation();
                        props.onDiscard();
                    }}
                >Discard</button>
            </div>
        : 
        <p className='card-description'>{props.item.description} </p>  
        }
    </div>
  )
}

export default Card

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 18:10:49