React.js如何实现点击列表项切换对应项的上下箭头图标
实现目标
点击列表项时,仅切换当前项的箭头图标:arrow-up和arrow-down来回切换,其余项图标不受影响。
原有代码问题
- 全局布尔状态
open是所有列表项共用的,值变更时所有项都会读取同一个状态,必然出现所有图标同步切换的问题 - 单独存
selectedIndex的写法只记录了最后点击的索引,没有处理「点击同一项时切换状态」的逻辑,无法实现来回切换的效果
修复方案
根据交互需求二选一即可:
方案1:手风琴模式(同一时间最多1个项展开)
同一时间只允许一个项显示向下箭头,点击已展开的项则收起,核心逻辑是判断当前点击项是否已激活,做对应值的切换:
import React, { useState } from "react"; import { ListGroup } from "react-bootstrap"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faAngleUp, faAngleDown } from "@fortawesome/free-solid-svg-icons"; export const defaultListData = [ { name: "Dapibus ac facilisis in" }, { name: "Morbi leo risus" }, { name: "Porta ac consectetur ac" }, { name: "Porta ac doesfvsaard asdas" } ]; function UserSettings() { // 初始值为null,默认所有项收起 const [activeIndex, setActiveIndex] = useState(null); const handleItemClick = (index) => { // 点击已展开的项就设为null收起,否则设为当前索引展开 setActiveIndex(activeIndex === index ? null : index); }; return ( <div> {defaultListData.map((category, i) => ( <ListGroup key={category.name} variant="flush"> <ListGroup.Item onClick={() => handleItemClick(i)} style={{ display: "flex", gap: "50px" }} > {category.name} <FontAwesomeIcon style={{ color: "green", cursor: "pointer" }} icon={activeIndex === i ? faAngleDown : faAngleUp} /> </ListGroup.Item> </ListGroup> ))} </div> ); } export default UserSettings;
方案2:独立控制模式(支持多个项同时展开)
如果需要点击多个项时,每个项的箭头状态独立保存、互不影响,就用数组存储每一项的展开状态:
function UserSettings() { // 初始化和列表长度一致的状态数组,默认全部为false(收起) const [openStatus, setOpenStatus] = useState( Array(defaultListData.length).fill(false) ); const handleItemClick = (index) => { setOpenStatus(prev => { const newStatus = [...prev]; // 仅翻转当前点击项的状态 newStatus[index] = !newStatus[index]; return newStatus; }) }; return ( <div> {defaultListData.map((category, i) => ( <ListGroup key={category.name} variant="flush"> <ListGroup.Item onClick={() => handleItemClick(i)} style={{ display: "flex", gap: "50px" }} > {category.name} <FontAwesomeIcon style={{ color: "green", cursor: "pointer" }} // 读取当前项自身的状态判断显示图标 icon={openStatus[i] ? faAngleDown : faAngleUp} /> </ListGroup.Item> </ListGroup> ))} </div> ); }
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

