ReactJS FAQ卡片 点击已展开项无法关闭的问题排查与修复
问题原因
你的手风琴点击已展开项无法收起的bug,核心问题出在hideText函数的执行逻辑上:
- 你把「展开当前点击项」的判断写在了for循环内部,每轮循环都会重复执行这段逻辑
- 当点击已经展开的项时,循环第一轮就会给这个项加上
not-active类执行收起,但紧接着同轮循环又会检测到这个项带有not-active类,马上把类移除重新展开,两个操作互相抵消,最终表现就是点击已展开项没有任何反应。
最小修改修复方案
不需要改动JSX结构,只需要重写hideText函数即可,修复后的逻辑为:
- 先记录当前点击项的初始展开状态
- 统一将所有答案项设置为收起状态
- 仅当点击项初始为收起状态时,才将其设置为展开;如果初始就是展开状态,保持全部收起即可
function hideText(element) { // 提前记录当前点击项是否处于展开状态 const isCurrentExpanded = !element.current.classList.contains("not-active"); // 所有项统一收起 elementsArray.forEach(item => { item.current.classList.add("not-active"); }); // 点击的是收起项才展开,点击展开项就保持全收起状态 if (!isCurrentExpanded) { element.current.classList.remove("not-active"); } }
React推荐写法(可选优化)
直接操作DOM class不符合React的状态驱动设计理念,你可以用useState管理当前展开项的索引,去掉冗余的ref定义,后续新增FAQ项也更方便:
import { useState } from "react"; import img_1 from "../images/bg-pattern-desktop.svg"; import img_2 from "../images/illustration-woman-online-desktop.svg"; export default function MainContent() { // null代表无展开项,值为索引时代表对应索引的项展开 const [openIndex, setOpenIndex] = useState(null); // FAQ配置数组,新增/修改项直接改数组即可 const faqConfig = [ { question: "How many team members can I invite?", answer: "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Temporibus obcaecati, quae, corporis." }, { question: "How many team members can I invite?", answer: "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Temporibus obcaecati, quae, corporis." }, { question: "How many team members can I invite?", answer: "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Temporibus obcaecati, quae, corporis." }, { question: "How many team members can I invite?", answer: "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Temporibus obcaecati, quae, corporis." }, { question: "How many team members can I invite?", answer: "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Temporibus obcaecati, quae, corporis." } ]; const toggleFaq = (index) => { // 点击已展开项则收起所有,点击其他项则展开对应项 setOpenIndex(openIndex === index ? null : index); }; return ( <> <div className="container"> <div className="imgBox"> <img src={img_1} alt="bg pattern" className="img_1" /> <img src={img_2} alt="woman online illustration" className="img_2" /> </div> <div className="textBox"> <h1>FAQ</h1> <div className="questions"> {faqConfig.map((item, index) => ( <div key={index}> <button onClick={() => toggleFaq(index)}> {item.question} </button> <p className={`p${index + 1} ${openIndex !== index ? "not-active" : ""}`}> {item.answer} </p> {index !== faqConfig.length - 1 && <hr />} </div> ))} </div> </div> </div> </> ); }
内容的提问来源于stack exchange,提问作者Steven Ashraf
相关产品推荐
相关产品推荐

