如何使用React-Grid-Layout实现动态宽高?React/JS自定义表单拖拽场景
React-Grid-Layout 高度同步失败解决思路
问题根因
ResponsiveGridLayout 默认采用内部状态维护布局数据,你直接修改原始fields数组中的layout属性不会被组件感知,且如果没有显式传入受控的layouts属性,组件不会响应外部布局数据的变更。
具体解决步骤
- 第一步:将组件切换为受控模式
显式声明state存储各断点的布局数据,将其作为layouts属性传入ResponsiveGridLayout,初始化时直接从fields数组提取layout配置。
示例代码:
给ResponsiveGridLayout补充受控属性:// 初始化布局state,多断点可按需扩展配置 const [layouts, setLayouts] = useState({ lg: fields.map(item => item.field.layout), md: fields.map(item => item.field.layout), sm: fields.map(item => item.field.layout), xs: fields.map(item => item.field.layout), xxs: fields.map(item => item.field.layout) })<ResponsiveGridLayout {/* 原有属性保持不变 */} layouts={layouts} > - 第二步:正确实现高度同步逻辑
在onDimensionChange回调中,采用不可变的方式更新layouts state,确保React能检测到状态变更,触发RGL重渲染。同时同步更新你的fields数组中的layout属性,保证全局数据一致。
示例代码:const onDimensionChange = (height, fieldId) => { setLayouts(prevLayouts => { const updatedLayouts = {...prevLayouts} // 遍历所有断点,更新对应字段的高度 Object.keys(updatedLayouts).forEach(breakpoint => { updatedLayouts[breakpoint] = updatedLayouts[breakpoint].map(item => { if (item.i === fieldId) { // 你设置了rowHeight=1,h值直接等于返回的像素高度即可 return {...item, h: height} } return item }) }) // 同步更新fields数组的layout配置 updateFields(updatedLayouts) return updatedLayouts }) } - 第三步:适配data-grid取值逻辑
渲染网格项时,data-grid属性优先从受控的layouts状态中取值,避免和fields数据不一致:<div key={field.field.id} ref={refs[idx]} data-grid={layouts.lg.find(item => item.i === field.field.id)} >
常见避坑点
- 不要直接修改layouts数组的原对象,必须通过展开运算符返回新的数组/对象,否则React不会触发状态更新
- 若无需多断点响应,可先使用非响应式的
GridLayout组件调试,逻辑验证通过后再切换回响应式版本 onLayoutChange回调触发时,要同步更新layouts state和fields数组,避免拖拽、缩放操作后数据回退
内容的提问来源于stack exchange,提问作者Worthy Dev
相关产品推荐
相关产品推荐

