React组件onClick事件处理:实现点击展开一个面板其余自动关闭
核心改造思路
当前每个ListItem组件独立维护自身的展开状态,组件之间没有状态关联,所以无法实现互斥展开。需要把展开状态提升到所有ListItem的公共父组件中,通过唯一标识符记录当前处于展开状态的模块,点击新模块时直接更新该标识符即可自动关闭原有展开的模块。
父组件实现
在渲染四个列表模块的父组件中统一维护展开状态,将激活状态和切换方法通过props传递给子组件:
import { useState } from 'react'; import ListItem from './ListItem'; // allListData为你存放四个模块所有数据的数组 function ListContainer({ allListData }) { // 存储当前展开项的唯一标识,null表示无展开项 const [activeId, setActiveId] = useState(null); const handleToggle = (id) => { // 点击已展开项则收起,否则切换为点击的项 setActiveId(activeId === id ? null : id); }; return ( <div className="List-wrapper"> {allListData.map((dataItem, idx) => ( <ListItem key={idx} listNumber={idx + 1} listData={dataItem} isActive={activeId === idx + 1} onToggle={handleToggle} /> ))} </div> ); }
子组件改造
删除ListItem内部的独立状态,改用父组件传递的props控制展开逻辑:
function ListItem({ listNumber, listData, isActive, onToggle }) { return ( <div className="List"> <div className="List-section" onClick={() => onToggle(listNumber)} > <div className="Section-item">{listNumber}</div> <p className="Section-title">{listData.title}</p> </div> {isActive && ( <div className="List-paragraph"> {listData.items.map((paragraphItem, index) => ( <div className="Paragraph-container" key={index}> <CheckedIcon /> <p className="Paragraph-item">{paragraphItem}</p> </div> ))} </div> )} </div> ); }
补充说明
如果你的listNumber存在重复的情况,可以改用数组索引作为唯一标识传递和判断。如果不需要支持点击已展开项自动收起的效果,直接把handleToggle方法内的逻辑修改为setActiveId(id)即可。
内容的提问来源于stack exchange,提问作者Jonas Petrauskas
相关产品推荐
相关产品推荐

