React.js中如何实现用户多选心形按钮的功能?
解决多选心形按钮的嵌套map问题
你遇到的按钮越点越多的问题,核心是错误地把选中项数组的map嵌套在了原始数据的map里——每次选中后,都会额外渲染选中项对应的按钮,导致DOM元素重复生成。正确的思路是:只基于原始数据渲染一次按钮,用选中数组判断每个按钮的选中状态即可。
具体实现步骤
- 用数组
selectedIds存储选中按钮的唯一标识(比如每个按钮对应的id) - 渲染时仅遍历原始数据生成按钮,通过
selectedIds判断是否给按钮添加选中样式 - 点击按钮时,切换该id在
selectedIds中的状态(已存在则移除,不存在则添加)
代码示例(React)
先看你可能踩坑的错误写法:
// 错误:嵌套map导致重复生成按钮 {data.map(item => ( <div key={item.id}> {selectedIds.map(id => ( <button className={id === item.id ? 'selected' : ''} onClick={() => handleClick(item.id)}> ❤️ </button> ))} </div> ))}
下面是正确的实现:
import { useState } from 'react'; function App() { // 原始按钮数据,每个项要有唯一id const heartItems = [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 } ]; // 存储选中按钮的id数组 const [selectedIds, setSelectedIds] = useState([]); const handleHeartClick = (id) => { setSelectedIds(prevState => { if (prevState.includes(id)) { // 已选中,从数组里移除 return prevState.filter(itemId => itemId !== id); } else { // 未选中,添加到数组 return [...prevState, id]; } }); }; return ( <div style={{ gap: '10px', display: 'flex', padding: '20px' }}> {/* 只遍历原始数据一次,生成所有按钮 */} {heartItems.map(item => ( <button key={item.id} style={{ border: 'none', fontSize: '24px', padding: '8px 16px', cursor: 'pointer', backgroundColor: selectedIds.includes(item.id) ? 'green' : 'white', color: selectedIds.includes(item.id) ? 'white' : 'inherit', borderRadius: '4px' }} onClick={() => handleHeartClick(item.id)} > ❤️ </button> ))} </div> ); } export default App;
关键注意点
- 永远只基于原始数据源渲染按钮,不要用选中数组重复渲染元素
selectedIds仅作为状态判断的依据,用来切换按钮的样式,不参与按钮的生成- 更新状态时用函数式更新(
prevState),确保拿到最新的状态值
内容的提问来源于stack exchange,提问作者nuser137
相关产品推荐
相关产品推荐

