React中使用useState实现点击移除数组元素的技术问询
实现点击按钮切换数组元素的添加/移除功能
这是个很典型的「选中/取消选中」交互需求,咱们只需要修改核心逻辑函数,同时完善按钮的选中状态反馈就能搞定。
第一步:修改handleAdd函数,实现Toggle逻辑
原来的代码里当值已存在时没有做任何操作,现在我们要补充「移除」的逻辑。另外,因为新状态依赖旧状态,推荐用函数式更新的方式调用setCheckCredit,这样能确保拿到最新的状态值,避免异步更新导致的问题:
function handleAdd(e, val) { setCheckCredit(prevCredit => { if (prevCredit.includes(val)) { // 值已存在,过滤掉该元素实现移除 return prevCredit.filter(item => item !== val); } else { // 值不存在,添加到数组中 return [...prevCredit, val]; } }); }
第二步:给按钮添加选中状态反馈
你的Card组件已经预留了selected属性,但之前的代码没正确传递这个值。现在我们可以根据checkCredit数组是否包含当前卡片的creditAvailable来设置这个属性,让用户能直观看到哪个按钮处于选中状态:
修改Cardlist里的Card渲染代码:
<Card id={detail.id} title={detail.title} apr={detail.apr} onClick={(e) => handleAdd(e, detail.creditAvailable)} balanceOfferDuration={detail.balanceOfferDuration} purchaseOfferDuration={detail.purchaseOfferDuration} creditAvailable={detail.creditAvailable} // 新增:判断当前卡片是否被选中 selected={checkCredit.includes(detail.creditAvailable)} />
第三步:优化底部金额显示格式
原来直接渲染数组会显示成逗号拼接的字符串,我们可以优化一下,数组为空时显示0,多个元素时用逗号分隔,体验更友好:
<div> Credit Available: £{checkCredit.length > 0 ? checkCredit.join(", ") : "0"} </div>
完整修改后的Cardlist组件代码
import React, { useState } from "react"; import PropTypes from "prop-types"; import Card from "./Card"; import { studentPayload, liquidCardPayload, anywhereCardPayload } from "../data/cardData"; const Cardlist = ({ incomeData, employmentData }) => { const [checkCredit, setCheckCredit] = useState([]); let payloads = [anywhereCardPayload]; // 简化卡片筛选逻辑,避免重复判断 if (employmentData === "student") { payloads.push(studentPayload); } if (incomeData >= 15000) { payloads.push(liquidCardPayload); } function handleAdd(e, val) { setCheckCredit(prevCredit => { if (prevCredit.includes(val)) { return prevCredit.filter(item => item !== val); } else { return [...prevCredit, val]; } }); } return ( <React.Fragment> {payloads.map(detail => ( <div key={detail.id}> {/* 用唯一id作为key比title更可靠 */} <Card id={detail.id} title={detail.title} apr={detail.apr} onClick={(e) => handleAdd(e, detail.creditAvailable)} balanceOfferDuration={detail.balanceOfferDuration} purchaseOfferDuration={detail.purchaseOfferDuration} creditAvailable={detail.creditAvailable} selected={checkCredit.includes(detail.creditAvailable)} /> </div> ))} <div> Credit Available: £{checkCredit.length > 0 ? checkCredit.join(", ") : "0"} </div> </React.Fragment> ); }; Cardlist.propTypes = { incomeData: PropTypes.string.isRequired, employmentData: PropTypes.string.isRequired }; export default Cardlist;
补充说明
- 函数式更新
setCheckCredit(prev => ...)是因为React状态更新可能异步,这样能确保基于最新状态修改,避免闭包导致的旧状态问题。 - 把
key从detail.title改成detail.id更可靠,因为标题可能重复,但id是唯一标识。 - 简化了卡片筛选逻辑,原来的重复判断可以合并,代码更简洁易读。
内容的提问来源于stack exchange,提问作者RogerBanks
相关产品推荐
相关产品推荐

