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

React结合Antd实现动态标签页时重复新增、关闭全标签问题排查

问题修复方案

根因分析

新增标签重复问题

  • React17 严格模式下 setState 的更新函数会执行两次用于副作用检测,你的 add 方法中直接对原 state 里的 panes 数组执行 push 操作,属于直接修改 state 的副作用操作,两次执行就会插入两个相同标签。
  • 浅拷贝 state 后 panes 数组引用未变,修改时直接污染了原 state。
  • 箭头函数定义的 add 方法在 constructor 中重复绑定 this,存在重复触发风险。
  • 未使用你预先定义的 newTabIndex 变量生成唯一 key,用 activeKey+1 的逻辑存在 key 重复隐患。

关闭标签清空+报错问题

  • remove 方法中错误直接遍历 state 对象(newState 是包含 activeKey、panes 属性的对象,不存在 forEach 方法),调用时报错导致后续逻辑异常,最终标签全部被清空。

修复后代码

import React from 'react';
import { Tabs, Button } from 'antd';
import 'antd/dist/antd.css';

const { TabPane } = Tabs;

class App extends React.Component {
  constructor(props) {
    super(props);
    this.newTabIndex = 0;
    const panes = [];

    this.state = {
      activeKey: '', // 初始无标签,设为空避免不匹配
      panes,
    };
    
    this.onChange = this.onChange.bind(this);
    this.onEdit = this.onEdit.bind(this);
  }

  onChange(activeKey) {
    this.setState({ activeKey });
  };

  onEdit(targetKey, action){
    this[action](targetKey);
  };

  add = (targetKey) => {
    this.setState(prevState => {
      // 生成新的panes数组,不修改原数组
      const newPane = {
        title: 'Tab ' + targetKey,
        content: 'Content of tab pane ' + targetKey,
        key: `tab-${this.newTabIndex++}` // 用自增变量生成唯一key
      }
      const newPanes = [...prevState.panes, newPane];
      return {
        panes: newPanes,
        activeKey: newPane.key // 新增后自动跳转到新标签
      }
    });
  };

  remove = (targetKey) => {
    this.setState(prevState => { 
      let lastIndex;
      // 遍历panes数组,不是state对象
      prevState.panes.forEach((pane, i) => {
        if (pane.key === targetKey) {
          lastIndex = i - 1;
        }
      });
      const panes = prevState.panes.filter(pane => pane.key !== targetKey);
      let activeKey = prevState.activeKey;
      if (panes.length && activeKey === targetKey) {
        if (lastIndex >= 0) {
          activeKey = panes[lastIndex].key;
        } else {
          activeKey = panes[0].key;
        }
      } else if (!panes.length) {
        activeKey = ''; // 标签全部删除后重置activeKey
      }
      return { panes, activeKey };
    });  
  };

  render() {
    return (
      <div className="tab-section">
        <div style={{ marginBottom: 16 }}>
          {
            ['1', '2', '3'].map(item => 
              <Button key={item} onClick={() => this.add(item)}>ADD Tab-{item}</Button>
            )
          }
        </div>
        <Tabs
          hideAdd
          onChange={this.onChange}
          activeKey={this.state.activeKey}
          type="editable-card"
          onEdit={this.onEdit}
        >
          {this.state.panes.map(pane => (
            <TabPane tab={pane.title} key={pane.key}>
              {pane.content}
            </TabPane>
          ))}
        </Tabs>
      </div>
    );
  }
}

export default App;

内容的提问来源于stack exchange,提问作者Thomas Deepak Konreddy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 16:27:02