React多折叠面板代码优化:单useState与统一onClick实现
简化React折叠面板的状态管理方案
核心优化思路
- 用单个状态变量管理当前展开的面板ID,替代多个独立的
useState - 用统一的事件处理函数切换面板状态,避免重复编写逻辑
- 把面板数据抽成数组,支持后续动态添加面板,无需修改组件核心逻辑
重构后的完整代码
import React, { useState } from "react"; import netflixLogo from "../images/netflix.png"; import "../sass/register.css"; import { Link } from "react-router-dom"; import Television from "../images/tv.png"; import NetflixExampleMovie from "../images/netflixExampleMovie.jpg"; import Computer from "../images/computer.png"; import KidsMovie from "../images/kidsMovie.png"; import { AiOutlinePlus } from "react-icons/ai"; function Register() { // 用单个state存储当前展开的面板ID,null表示全部收起 const [activePanel, setActivePanel] = useState(null); // 统一的面板切换函数 const handlePanelToggle = (panelId) => { // 如果点击的是当前展开的面板,就收起;否则展开该面板 setActivePanel(prev => prev === panelId ? null : panelId); }; // 定义所有折叠面板的数据,后续新增面板直接往数组里加即可 const faqPanels = [ { id: "first", title: "第一个问题的标题", content: "这里是第一个问题的回答内容..." }, { id: "second", title: "第二个问题的标题", content: "这里是第二个问题的回答内容..." }, { id: "third", title: "第三个问题的标题", content: "这里是第三个问题的回答内容..." }, { id: "fourth", title: "How do I cancel?", content: "Netflix is flexible. There are no pesky contracts and no commitments. You can easily cancel your account online in two clicks. There are no cancellation fees – start or stop your account anytime." }, { id: "fifth", title: "第五个问题的标题", content: "这里是第五个问题的回答内容..." }, { id: "sixth", title: "第六个问题的标题", content: "这里是第六个问题的回答内容..." } ]; return ( <div> {/* 保留原有其他代码... */} {/* 循环渲染所有折叠面板 */} {faqPanels.map(panel => ( <div key={panel.id} className={`asked asked${panel.id.charAt(0).toUpperCase() + panel.id.slice(1)}`}> <button className="askedButton" onClick={() => handlePanelToggle(panel.id)}> <span>{panel.title}</span> <AiOutlinePlus className={`plusIcon ${activePanel === panel.id ? "rotate" : ""}`} /> </button> <div className={`answer answer${panel.id.charAt(0).toUpperCase() + panel.id.slice(1)} ${activePanel === panel.id ? "block" : ""}`} > <p className={activePanel === panel.id ? "collapse" : ""}> {panel.content} </p> </div> </div> ))} {/* 保留原有其他代码... */} </div> ); } export default Register;
关键细节说明
- 状态管理:
activePanel存储当前展开的面板ID,初始值null表示所有面板默认收起;如果需要默认展开某个面板,把初始值改成对应ID即可(比如useState("fourth"))。 - 切换逻辑:
handlePanelToggle函数接收面板ID,通过判断当前状态决定是展开还是收起该面板,同时自动关闭其他面板。 - 动态扩展性:新增面板时,只需要在
faqPanels数组里添加新的对象,组件会自动渲染,无需修改状态和事件逻辑。 - 类名控制:通过
activePanel === panel.id判断当前面板是否展开,动态添加对应的CSS类(比如rotate、block、collapse)。
内容的提问来源于stack exchange,提问作者voskid
相关产品推荐
相关产品推荐

