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

React+TypeScript+Ant Design折叠面板的数据传递与激活控制问题

React+TypeScript+Ant Design折叠面板的数据传递与激活控制问题

我来帮你搞定这个折叠面板的问题,咱们先梳理下现有代码里的几个核心问题,再一步步修正:

现有代码的问题点

  • Collapse的onChange逻辑错误:你现在的onChange={() => setActiveKey(activeKey)}没用到回调里的实际选中key,应该接收参数来更新状态
  • 硬编码activeKey值:直接写死handleClick('2')太不灵活,而且没法关联数据传递
  • 缺少数据传递的状态载体:Element1里的car数据没有渠道传到Element2
  • 未区分打开面板的场景:没法判断用户是点击按钮打开Element2,还是直接点击面板标题打开的

解决方案思路

  1. 新增两个状态:一个存要传递的车辆数据selectedCar,一个标记是否通过按钮打开面板isOpenedByButton
  2. 让Element1不仅通知父组件切换面板,还要把car数据传上去
  3. 给Element2传递props,根据isOpenedByButton和selectedCar来决定展示内容
  4. 修正Collapse的onChange逻辑:点击面板标题切换时,清空数据并标记为非按钮触发;点击按钮切换时,保存数据并标记为按钮触发

完整修正代码

import React, { useState } from 'react';
import { Collapse, Button } from 'antd';

// 定义车辆数据类型,复用类型
type Car = { type: string; model: string; year: number };

// Element1的Props类型,新增传递数据的回调
interface Element1Props {
  onOpenNextPanel: (car: Car) => void;
}

const Element1: React.FC<Element1Props> = ({ onOpenNextPanel }) => {
  const car: Car = { type: "Toyota", model: "Corolla", year: 2009 };

  const handleButtonClick = () => {
    // 点击按钮时,把car数据传给父组件,同时触发面板切换
    onOpenNextPanel(car);
  };

  return (
    <div>
      <Button onClick={handleButtonClick}>
        点击打开下一面板并传递数据
      </Button>
    </div>
  );
};

// Element2的Props类型
interface Element2Props {
  selectedCar?: Car;
  isOpenedByButton: boolean;
  onBack: () => void;
}

const Element2: React.FC<Element2Props> = ({ selectedCar, isOpenedByButton, onBack }) => {
  if (!isOpenedByButton) {
    // 直接点击面板标题打开的情况,显示提示
    return (
      <div>
        <p>请回到第一个面板,点击按钮打开这里</p>
        <Button onClick={onBack}>返回上一面板</Button>
      </div>
    );
  }

  // 按钮触发打开的情况,展示传递过来的车辆数据
  return (
    <div>
      <h3>车辆详情</h3>
      <p>品牌:{selectedCar?.type}</p>
      <p>型号:{selectedCar?.model}</p>
      <p>年份:{selectedCar?.year}</p>
      <Button onClick={onBack}>返回上一面板</Button>
    </div>
  );
};

const CollapseComponent = () => {
  const [activeKey, setActiveKey] = useState<string>('1'); // 默认打开第一个面板
  const [selectedCar, setSelectedCar] = useState<Car>();
  const [isOpenedByButton, setIsOpenedByButton] = useState(false);

  // 处理通过按钮打开面板的逻辑
  const handleOpenNextPanel = (car: Car) => {
    setSelectedCar(car);
    setIsOpenedByButton(true);
    setActiveKey('2');
  };

  // 处理Collapse的切换(点击面板标题触发)
  const handleCollapseChange = (key: string) => {
    // 如果是点击标题打开第二个面板,清空数据并标记非按钮触发
    if (key === '2') {
      setSelectedCar(undefined);
      setIsOpenedByButton(false);
    }
    setActiveKey(key);
  };

  // 返回上一面板的逻辑
  const handleBack = () => {
    setActiveKey('1');
  };

  return (
    <Collapse activeKey={activeKey} onChange={handleCollapseChange}>
      <Collapse.Panel header="Element1" key="1">
        <Element1 onOpenNextPanel={handleOpenNextPanel} />
      </Collapse.Panel>
      <Collapse.Panel header="Element2" key="2">
        <Element2
          selectedCar={selectedCar}
          isOpenedByButton={isOpenedByButton}
          onBack={handleBack}
        />
      </Collapse.Panel>
    </Collapse>
  );
};

export default CollapseComponent;

关键说明

  • 用selectedCar状态存储要传递的车辆数据,isOpenedByButton区分打开场景,完美实现“按钮打开传数据,标题打开空内容”的需求
  • 去掉了硬编码的key值,通过父组件的状态统一管理面板切换,更灵活可扩展
  • 修正了Collapse的onChange回调,正确接收切换后的key参数,处理不同场景的状态更新
  • 所有组件都明确了Props类型,符合TypeScript的类型规范

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 11:48:10