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内导致事件冲突。
核心问题与修复方案
问题根源
- 函数未执行:Card组件的按钮点击事件中仅引用了
props.onPress和props.onDiscard,未添加()执行函数,导致点击时无响应; - 事件冒泡冲突:按钮点击事件会向上冒泡触发父div的onClick事件,干扰状态切换逻辑;
- 条件判断错误:Back按钮的判断条件误用了
props.item.selected,而数据结构中实际使用state字段存储状态。
修复步骤
- 在按钮的onClick回调中执行函数:将
props.onPress改为props.onPress(),props.onDiscard改为props.onDiscard(); - 调用
event.stopPropagation()阻止事件冒泡,避免触发父元素的点击事件; - 修正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
相关产品推荐
相关产品推荐

