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

如何实现类似CodeSandbox控制台的可拖拽拆分面板并修复状态冲突?

解决拖拽拆分面板的状态同步问题

问题分析

原代码通过toExpand状态条件渲染面板并设置preferredSize,但拖拽操作会直接修改面板尺寸却不更新状态,导致箭头图标和实际面板状态不一致。核心问题是状态和面板实际尺寸没有双向同步。

解决方案

不需要条件渲染面板,始终保留Console面板,通过监听面板尺寸变化同步状态,点击标题时切换面板的展开/收起尺寸:

修改后的代码

import React from "react";
import { Allotment } from "allotment";
import "allotment/dist/style.css";
import styles from "./App.module.css";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      consoleSize: 0, // 记录Console面板的尺寸
    };
  }

  // 切换面板展开/收起
  toggleConsole = () => {
    this.setState(prev => ({
      consoleSize: prev.consoleSize === 0 ? "50%" : 0
    }));
  };

  // 监听面板尺寸变化,同步状态
  handleResize = (sizes) => {
    // sizes是数组,第二个元素是Console面板的尺寸
    this.setState({ consoleSize: sizes[1] });
  };

  render() {
    const isExpanded = this.state.consoleSize > 0;
    return (
      <div className={styles.container}>
        <Allotment vertical onResize={this.handleResize}>
          <Allotment.Pane>abc</Allotment.Pane>
          <Allotment.Pane preferredSize={this.state.consoleSize}>
            <div onClick={this.toggleConsole} style={{ cursor: "pointer" }}>
              Console &nbsp;
              {isExpanded ? "ArrowDown" : "ArrowUp"}
            </div>
          </Allotment.Pane>
        </Allotment>
      </div>
    );
  }
}

关键改进点

  • 移除条件渲染:始终保留Console面板,避免拖拽时DOM重新渲染导致的冲突
  • 双向同步状态:通过onResize监听面板尺寸变化,实时更新consoleSize状态,确保箭头图标和实际面板状态一致
  • 统一尺寸控制:点击标题时直接修改consoleSize,Allotment会自动更新面板尺寸,拖拽操作也会同步更新状态

替代方案(使用react-split-pane)

如果allotment的使用体验不符合预期,可以尝试react-split-pane库,实现逻辑类似:

import React, { useState } from "react";
import SplitPane from "react-split-pane";
import "react-split-pane/lib/react-split-pane.css";

export default function App() {
  const [consoleSize, setConsoleSize] = useState(0);
  const isExpanded = consoleSize > 0;

  const toggleConsole = () => {
    setConsoleSize(prev => prev === 0 ? "50%" : 0);
  };

  return (
    <SplitPane
      split="vertical"
      defaultSize="100%"
      secondarySize={consoleSize}
      onChange={size => setConsoleSize(size)}
    >
      <div>abc</div>
      <div>
        <div onClick={toggleConsole} style={{ cursor: "pointer" }}>
          Console &nbsp;
          {isExpanded ? "ArrowDown" : "ArrowUp"}
        </div>
      </div>
    </SplitPane>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:15:51