React FAQ手风琴组件改造:实现多问题同时展开功能
解决React FAQ手风琴多问题同时展开的方案
原代码只能单问题展开的核心原因是用单个值selected记录展开状态,每次切换都会覆盖之前的记录。要实现多开,需要改成用数组存储所有展开的问题ID,具体修改步骤如下:
1. 修改状态定义
把单个值状态改为数组,初始为空数组(默认所有问题都收起):
const [selectedIds, setSelectedIds] = useState([]);
2. 重写toggle逻辑
点击按钮时,判断当前问题ID是否已在展开列表中:
- 存在则移除(收起该问题)
- 不存在则添加(展开该问题)
const toggle = (id) => { setSelectedIds(prevIds => { if (prevIds.includes(id)) { // 移除ID,收起问题 return prevIds.filter(item => item !== id); } else { // 添加ID,展开问题 return [...prevIds, id]; } }); };
3. 更新渲染判断
判断当前问题ID是否在selectedIds数组中,以此控制内容显示和按钮文字:
完整修改后的代码
import React, { useState } from "react"; import "./faq.css"; function Faq() { // 用数组存储所有展开的问题ID const [selectedIds, setSelectedIds] = useState([]); const toggle = (id) => { setSelectedIds(prevIds => { if (prevIds.includes(id)) { return prevIds.filter(item => item !== id); } else { return [...prevIds, id]; } }); }; return ( <div className="container"> <h2>Frequently Asked Questions</h2> <div className="questions"> {Questions.map((question) => ( <div key={question.id}> <h4> {question.title} <button onClick={() => toggle(question.id)}> {/* 判断当前ID是否在展开列表中,切换按钮文字 */} {selectedIds.includes(question.id) ? "X" : "+"} </button> </h4> {/* 根据ID是否在列表中控制内容显示 */} <p className={selectedIds.includes(question.id) ? "question-info" : "hidden"} > {question.info} </p> </div> ))} </div> </div> ); } export default Faq;
额外优化(可选)
如果你的Questions数据量较大,用数组的includes方法性能可能略低,也可以改用Set来存储展开ID,判断和增删操作会更高效:
const [selectedIds, setSelectedIds] = useState(new Set()); const toggle = (id) => { setSelectedIds(prevSet => { const newSet = new Set(prevSet); if (newSet.has(id)) { newSet.delete(id); } else { newSet.add(id); } return newSet; }); }; // 渲染时判断改为 selectedIds.has(question.id)
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

