React-Grid-Layout如何动态修改ResponsiveReactGridLayout的cols
问题原因
你遇到的报错:
Unhandled Runtime Error
Error: ResponsiveReactGridLayout:colsentry for breakpoint lg is missing!
触发核心原因是ResponsiveReactGridLayout强制要求传入的cols配置键,必须和当前生效的断点一一对应,你的代码存在4处问题导致校验失败:
- 未显式传入
breakpoints属性,完全依赖组件内置默认断点规则,动态更新cols时如果组件内部断点计算和state更新时机不同步,就会找不到对应断点的cols配置 - 图片
onLoad事件触发早期阶段,img元素尺寸可能还没完成布局计算,img.offsetWidth / 100算出的numCols可能为0,非法列数会直接导致组件内部校验不通过 - 组件属性传递顺序错误:你把
{...this.props}放在自定义属性前面,如果上层组件传入的props中包含cols/breakpoints字段,会直接覆盖你从state中读取的配置,最终传入组件的cols配置缺项 setState中重复定义了两次cols字段,属于冗余代码,虽然JS语法中后定义的值会覆盖前者不会直接报错,但很容易引发后续维护问题
正确实现方式
按照以下步骤修改即可解决问题:
- 显式定义和cols键完全匹配的breakpoints常量,固定断点规则,不依赖组件默认值
- 给列数、行数的计算结果加最小值兜底,保证列数/行数最小为1,避免传入非法值
- 调整组件props传递顺序,把自定义的
breakpoints、cols等核心配置放在{...this.props}后面,防止被上层传入的props覆盖 - 在
onBreakpointChange回调中增加配置兜底校验,断点切换时如果发现对应断点的cols缺失,自动补全默认值
修复后核心代码
// 类组件中固定断点配置,和cols的键严格对应 defaultBreakpoints = { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 } constructor(props) { super(props); this.state = { cols: { lg: 12, md: 12, sm: 12, xs: 12, xxs: 12 }, rowHeight: 100, items: _.range(0, 36).map(function (i) { return { i: i.toString(), x: i % 12, y: Math.floor(i / 12), w: 1, h: 1, initCell: true, draggable: false, static: true, isBounded: true, }; }), newCounter: 0, dimensions: { height: 0, width: 0 }, mounted: true // 补全原代码缺失的mounted状态初始化,避免useCSSTransforms取到undefined }; this.onImgLoad = this.onImgLoad.bind(this); this.onAddItem = this.onAddItem.bind(this); this.onBreakpointChange = this.onBreakpointChange.bind(this); } onImgLoad({ target: img }) { // 计算列数行数时加最小值兜底,避免算出0的非法值 const numCols = Math.max(1, Math.round(img.offsetWidth / 100)); const numRows = Math.max(1, Math.round(img.offsetHeight / 100)); this.setState({ cols: { lg: numCols, md: numCols, sm: numCols, xs: numCols, xxs: numCols }, rowHeight: 100, items: _.range(0, numCols * numRows).map(function (i) { return { i: i.toString(), x: i % numCols, y: Math.floor(i / numCols), w: 1, h: 1, initCell: true, draggable: false, static: true, isBounded: true, }; }), dimensions: { height: img.offsetHeight, width: img.offsetWidth }, newCounter: 0, }); } // 增加断点切换兜底校验 onBreakpointChange(breakpoint) { if (!this.state.cols[breakpoint]) { this.setState(prev => ({ cols: { ...prev.cols, [breakpoint]: 12 } })) } } // 渲染部分调整props顺序 render() { return ( <> <img onLoad={this.onImgLoad} src={src} /> <ResponsiveReactGridLayout onLayoutChange={this.onLayoutChange} onBreakpointChange={this.onBreakpointChange} onDrop={this.onDrop} measureBeforeMount={false} useCSSTransforms={this.state.mounted} compactType={null} isResizable={false} allowOverlap={true} isDroppable={true} isBounded={true} margin={[0, 0]} style={{ backgroundImage: "url(" + src + ")", backgroundPosition: "center", backgroundSize: "100% 100%", backgroundRepeat: "no-repeat", }} {...this.props} {/* 核心配置放在扩展运算符后面,避免被上层props覆盖 */} breakpoints={this.defaultBreakpoints} cols={this.state.cols} > {/* 原有grid item渲染逻辑 */} </ResponsiveReactGridLayout> </> ) }
内容的提问来源于stack exchange,提问作者ggever
相关产品推荐
相关产品推荐

