You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

关键细节说明

  1. 状态管理:activePanel存储当前展开的面板ID,初始值null表示所有面板默认收起;如果需要默认展开某个面板,把初始值改成对应ID即可(比如useState("fourth"))。
  2. 切换逻辑:handlePanelToggle函数接收面板ID,通过判断当前状态决定是展开还是收起该面板,同时自动关闭其他面板。
  3. 动态扩展性:新增面板时,只需要在faqPanels数组里添加新的对象,组件会自动渲染,无需修改状态和事件逻辑。
  4. 类名控制:通过activePanel === panel.id判断当前面板是否展开,动态添加对应的CSS类(比如rotate、block、collapse)。

内容的提问来源于stack exchange,提问作者voskid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:45:24