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

基于React的可拖拽可调整大小的Material UI Dialog组件问题排查

解决Material UI Dialog结合react-draggable/react-resizable的两个问题

问题1:全屏后ResizableBox尺寸不更新

解决方案

核心思路是监听Dialog的fullscreen状态变化,通过Ref获取Paper组件的实际尺寸,同步更新ResizableBox的宽高。之前用Ref获取尺寸失败,大概率是因为没有在状态变化后读取最新的DOM尺寸。

代码示例

import { useState, useEffect, useRef } from 'react';
import Dialog from '@mui/material/Dialog';
import Draggable from 'react-draggable';
import { ResizableBox } from 'react-resizable';
import 'react-resizable/css/styles.css';

const CustomDraggableResizableDialog = ({ open, fullscreen, defaultWidth = 500, defaultHeight = 400, ...props }) => {
  const paperRef = useRef(null);
  const [resizableSize, setResizableSize] = useState({
    width: defaultWidth,
    height: defaultHeight
  });

  // 监听全屏状态变化,同步尺寸
  useEffect(() => {
    if (!paperRef.current) return;

    if (fullscreen) {
      const { offsetWidth, offsetHeight } = paperRef.current;
      setResizableSize({ width: offsetWidth, height: offsetHeight });
    } else {
      setResizableSize({ width: defaultWidth, height: defaultHeight });
    }
  }, [fullscreen, defaultWidth, defaultHeight]);

  return (
    <Dialog
      open={open}
      fullscreen={fullscreen}
      PaperProps={{
        ref: paperRef,
        sx: {
          position: 'absolute', // 配合react-draggable的定位逻辑
          overflow: 'hidden' // 提前规避滚动条问题
        }
      }}
      {...props}
    >
      <Draggable handle=".dialog-header" bounds="parent">
        <div>
          {/* 拖拽手柄区域 */}
          <div className="dialog-header" style={{ padding: '12px', cursor: 'move', backgroundColor: '#f5f5f5' }}>
            可拖拽对话框
          </div>
          <ResizableBox
            width={resizableSize.width}
            height={resizableSize.height}
            resizeHandles={['e', 's', 'se']}
            minConstraints={[300, 200]}
            style={{ boxSizing: 'border-box' }}
            onResizeStop={(e, data) => setResizableSize({
              width: data.size.width,
              height: data.size.height
            })}
          >
            {/* 对话框内容区域 */}
            <div style={{ padding: '16px', height: '100%' }}>
              这里是对话框内容
            </div>
          </ResizableBox>
        </div>
      </Draggable>
    </Dialog>
  );
};

export default CustomDraggableResizableDialog;

问题2:设置resizeHandles后出现滚动条

解决方案

滚动条出现的核心原因是resize手柄占用了额外空间,导致内容区域超出Paper的边界。通过以下两步解决:

  1. 给ResizableBox添加box-sizing: border-box,让手柄的宽度包含在元素自身尺寸内,不额外占用空间
  2. 给Dialog的Paper设置overflow: hidden,直接隐藏超出边界的内容(如果内容确实需要滚动,可以单独给内容区域设置overflow: auto)

关键代码点

  • ResizableBox的style={{ boxSizing: 'border-box' }}
  • PaperProps的sx: { overflow: 'hidden' }

如果内容区域需要滚动,把内容容器的样式改成:

<div style={{ padding: '16px', height: '100%', overflow: 'auto' }}>
  长内容区域...
</div>

内容的提问来源于stack exchange,提问作者Susitha Ravinda Senarath

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 04:30:10