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

React递归组件使用Hooks实现一键展开全部子元素功能求助

解决方案:实现点击Expand按钮展开对应父元素下所有层级子元素

问题分析

当前代码里,App组件的expandAll是全局布尔值,没法精准控制单个父元素的全展开;MainAccordion也没处理递归展开所有子元素的逻辑,导致点击Expand按钮达不到预期效果。

修改步骤与代码实现

1. 调整App组件状态与逻辑

把全局的expandAll布尔值改成记录需要全展开项的集合,精准控制单个父元素:

// App.js
function App() {
  // 用Set存储需要全展开的项的title,支持切换展开/取消状态
  const [expandedFullItems, setExpandedFullItems] = useState(new Set());
  const [data, setData] = useState(manipulateData(originalData));

  const handleExpand = (title) => {
    setExpandedFullItems(prev => {
      const newSet = new Set(prev);
      if (newSet.has(title)) {
        newSet.delete(title);
      } else {
        newSet.add(title);
      }
      return newSet;
    });
  };

  return (
    <div className="App">
      {data.map((item) => (
        <div key={item.title} style={{display:"flex",justifyContent:"space-between"}}>
          {/* 传递全展开集合,以及当前项是否被标记为全展开 */}
          <MainAccordion 
            item={item} 
            isFullExpanded={expandedFullItems.has(item.title)}
            expandedFullItems={expandedFullItems}
          />
          <div style={{padding:"2px", cursor: "pointer"}} onClick={()=>handleExpand(item.title)}>
            {/* 根据状态切换显示文本 */}
            {expandedFullItems.has(item.title) ? "Collapse All" : "Expand All"}
          </div>
        </div>
      ))}
    </div>
  );
}

export default App;

2. 修改MainAccordion组件,支持递归全展开

新增isFullExpanded属性判断当前项是否需要强制全展开,同时将该状态传递给子元素,实现所有层级递归展开:

// MainAccordion.js
import { useEffect, useState } from "react";

function MainAccordion({ item, isFullExpanded = false, expandedFullItems }) {
  const [collapse, setCollapse] = useState(false);
  const [child, setChild] = useState([]);

  const handleClick = () => {
    // 手动点击标题时,覆盖全展开的自动状态
    setCollapse(!collapse);
  };

  const getData = (item) => {
    const arr = Array.from(item.children, function (entry) {
      return { key: entry[0], value: entry[1] };
    });
    setChild(arr);
  };

  useEffect(() => {
    if (item.children){
      getData(item);
    } 
  }, [item.children]);

  // 监听全展开状态,自动设置折叠状态
  useEffect(() => {
    if (isFullExpanded) {
      setCollapse(true);
    }
  }, [isFullExpanded]);

  // 判断子项是否需要全展开:当前项全展开,或子项自身被标记为全展开
  const getChildFullExpanded = (childItem) => {
    return isFullExpanded || expandedFullItems.has(childItem.title);
  };

  return (
    <div style={{ paddingLeft: 10, cursor: "pointer" }}>
      <div onClick={handleClick}>{item.title}</div>
      {collapse && item.children && child.map((childItem) => (
        <div key={childItem.key} style={{ paddingLeft: 10 }}>
          <MainAccordion 
            item={childItem.value} 
            isFullExpanded={getChildFullExpanded(childItem.value)}
            expandedFullItems={expandedFullItems}
          />
        </div>
      ))}
    </div>
  );
}

export default MainAccordion;

关键逻辑说明

  • 精准控制单个项:用Set存储需要全展开的项的title,避免全局布尔值影响所有元素。
  • 递归展开:将当前项的isFullExpanded状态传递给子元素,子元素自动判断是否展开,实现所有层级自动展开。
  • 操作优先级:手动点击标题切换折叠状态时,会覆盖全展开的自动状态,保证用户手动操作的优先级。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:06:35