React JS中如何触发.map()渲染列表中的指定单个元素
手风琴组件单条展开问题修复
问题根源
所有渲染的列表项共用了同一个布尔类型的display状态,状态变更时所有项都会同步触发渲染逻辑,无法区分当前被点击的具体项,因此会出现全展开/全折叠的联动问题。
修复实现(单开模式:同一时间仅展开一项)
把状态从布尔值改为存储当前展开项的唯一ID,通过ID匹配判断每一项的展开状态:
import { useState } from "react"; import { AiFillPlusCircle, AiFillMinusCircle } from "react-icons/ai"; import data from "../data"; export default function Container() { // 存储当前展开项的id,初始为null代表默认全折叠 const [activeId, setActiveId] = useState(null); const clickHandle = (id) => { // 点击已展开的项则折叠,否则展开当前点击项 setActiveId(activeId === id ? null : id); }; return ( <> <div className="fContainer container"> <div className="headingContainer"> <h2 className="mainHeading">Questions And Answers About Login</h2> </div> <div className="fQuesContainer container"> {data.map((question) => { const { id, title, info } = question; // 仅当前项id匹配激活id时为展开状态 const isOpen = activeId === id; return ( <div className="qCard" key={id}> <div className="qCardTitle"> <h4 className="qTitle">{title}</h4> <button className="btnContainer" onClick={() => clickHandle(id)}> {isOpen ? ( <AiFillMinusCircle size="2.4em" /> ) : ( <AiFillPlusCircle size="2.4em" /> )} </button> </div> {isOpen && ( <> <hr className="fHr" /> <p className="fInfo">{info}</p> </> )} </div> ); })} </div> </div> </> ); }
扩展:多开模式实现(支持同时展开多个项)
如果需要支持同时展开多个手风琴项,把状态改为存储已展开项的ID数组即可:
// 初始为空数组,默认全折叠 const [openIds, setOpenIds] = useState([]); const clickHandle = (id) => { setOpenIds(prev => prev.includes(id) ? prev.filter(itemId => itemId !== id) // 已存在则移除(折叠) : [...prev, id] // 不存在则加入(展开) ) } // 渲染时判断逻辑改为 const isOpen = openIds.includes(id);
效果参考
- 折叠状态:

- 单条展开状态:

内容的提问来源于stack exchange,提问作者Ankit Sharma
相关产品推荐
相关产品推荐

