在React的.map()函数中如何实现单个元素的class类切换?
问题原因
你所有列表项共用了同一个布尔类型的全局状态,状态变更后所有绑定了该状态的元素都会同步变更类名,所以会出现点击一个所有都变的问题。
修复方案
将状态从布尔值改为存储当前激活项的用户ID,切换时只匹配对应ID的项即可实现单个元素类名切换,修复后代码如下:
const ItemList: React.FC<ListItemUserProps> = (props) => { const { items } = props; // 状态改为存储当前激活项的userId,初始为null代表无激活项 const [activeUserId, setActiveUserId] = useState<number | string | null>(null); function toggleUserOpt(userId: number | string) { // 点击相同项则关闭,否则切换为当前点击项 setActiveUserId(prev => prev === userId ? null : userId); } return ( <> {items.map((t) => ( <React.Fragment key={t.userId}> <div className={`item ${activeUserId === t.userId ? 'show' : 'hide'}`} role="button" tabIndex={0} onClick={() => toggleUserOpt(t.userId)} onKeyDown={(e) => { // 仅回车和空格触发切换,符合无障碍规范 if (['Enter', ' '].includes(e.key)) { toggleUserOpt(t.userId) } }} > {t.userNav.firstName} </div> </React.Fragment> ))} </> ); }; export default ItemList;
拓展:支持多项同时切换
如果业务需要支持多个项同时展示类,将状态改为存储ID集合即可:
// 初始为空集合,代表无选中项 const [activeUserIds, setActiveUserIds] = useState<Set<number | string>>(new Set()); function toggleUserOpt(userId: number | string) { setActiveUserIds(prev => { const newSet = new Set(prev); newSet.has(userId) ? newSet.delete(userId) : newSet.add(userId); return newSet; }) } // 类名判断逻辑调整为判断集合中是否存在当前项ID className={`item ${activeUserIds.has(t.userId) ? 'show' : 'hide'}`}
内容的提问来源于stack exchange,提问作者Alessandro
相关产品推荐
相关产品推荐

