React Grid Layout (RGL)
React-Grid-Layout (RGL) is a powerful and flexible grid layout system for React applications, enabling draggable and resizable components with responsive breakpoint support. Unlike older solutions like Packery or Gridster, RGL is built purely with React, avoiding external dependencies such as jQuery. The current stable version is 2.2.3, with frequent patch releases addressing bugs and minor enhancements. Version 2.0.0 marked a significant rewrite, introducing a full TypeScript codebase and a modernized Hooks-based API for improved composability and performance. Key differentiators include its robust responsive behavior, native React implementation, and first-class TypeScript support since version 2, making it suitable for complex, enterprise-grade dashboards and user interfaces. Releases occur frequently for bug fixes and minor features, typically multiple times per month for patch versions.
Common errors
-
Error: "React-Grid-Layout: The width property is required!"
cause Using `ReactGridLayout` directly (without `WidthProvider`) in v2.0.0+ without providing a `width` prop.fixWhen using `ReactGridLayout` directly, you must explicitly pass a `width` prop. If using `Responsive`, ensure it's wrapped with `WidthProvider`. -
TypeError: Cannot read properties of undefined (reading 'map') at getLayoutItem
cause The `layout` prop (or `layouts` for `Responsive`) is not an array of valid layout objects, or is `undefined`.fixEnsure that the `layout` prop is an array where each item is an object with at least `i` (id), `x`, `y`, `w`, and `h` properties. Initialize it to an empty array (`[]`) if there are no items initially. -
ResizeObserver loop limit exceeded
cause Rapid and frequent DOM mutations within the grid could trigger a ResizeObserver to report changes repeatedly, leading to an infinite loop. This was a known issue in versions prior to 2.2.3.fixUpgrade to `react-grid-layout@2.2.3` or a later version. The library now defers state updates to prevent this error. -
ReferenceError: require is not defined in ES module scope
cause Attempting to use CommonJS `require()` syntax (`const RGL = require('react-grid-layout');`) in a modern ESM-only project context.fixUse ESM `import` statements (e.g., `import { Responsive } from 'react-grid-layout';`). Ensure your project's `package.json` specifies `"type": "module"` if you intend to use ESM exclusively, or configure your bundler (Webpack, Rollup, Vite) correctly.
Warnings
- breaking Version 2.0.0 introduced a complete TypeScript rewrite and a modernized Hooks API, breaking compatibility with v1's flat props API. Many props were grouped into config objects (e.g., `gridConfig`, `dragConfig`).
- breaking Since v2.0.0, the `width` prop is now explicitly required for `ReactGridLayout`. While `Responsive` components typically handle this via `WidthProvider`, direct usage of `ReactGridLayout` without `WidthProvider` will require manual width provisioning.
- breaking The `onDragStart` callback in v2.0.0 now fires after a 3px movement threshold, rather than on `mousedown`. This prevents unintended drag events from simple clicks.
- breaking Callback parameters (e.g., in `onDrag`, `onResize`) are immutable in v2.0.0. Direct mutation of the layout array or individual layout items within these callbacks is no longer supported and can lead to unexpected behavior.
- gotcha Version 2.2.0 contained a critical layout bug that could lead to incorrect grid positioning and behavior. It was quickly patched in subsequent releases.
- gotcha Older versions (pre-2.2.3) could encounter a 'ResizeObserver loop limit exceeded' error, particularly when rapidly resizing or dragging elements, due to state update timing.
Install
-
npm install react-grid-layout -
yarn add react-grid-layout -
pnpm add react-grid-layout
Imports
- Responsive
import Responsive from 'react-grid-layout';
import { Responsive, WidthProvider } from 'react-grid-layout'; - Layout
import { Layout as RGL_Layout } from 'react-grid-layout/legacy';import { Layout } from 'react-grid-layout'; - useResponsiveLayout
import { useResponsiveLayout } from 'react-grid-layout';import { useResponsiveLayout } from 'react-grid-layout/hooks';
Quickstart
import React, { useState } from 'react';
import { Responsive, WidthProvider, Layout } from 'react-grid-layout';
import 'react-grid-layout/css/styles.css';
import 'react-resizable/css/styles.css';
// WidthProvider is a HOC that provides the width prop to the Responsive grid.
const ResponsiveGridLayout = WidthProvider(Responsive);
const MyResponsiveDashboard: React.FC = () => {
const [currentLayout, setCurrentLayout] = useState<Layout[]>([
{ i: 'a', x: 0, y: 0, w: 1, h: 2 },
{ i: 'b', x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 },
{ i: 'c', x: 4, y: 0, w: 1, h: 2 }
]);
// Define responsive breakpoints and column counts
const breakpoints = { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 };
const cols = { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 };
const onLayoutChange = (layout: Layout[], layouts: { [key: string]: Layout[] }) => {
// Save the current layout state, e.g., to local storage or a backend
console.log('Layout changed:', layout);
setCurrentLayout(layout);
};
return (
<div style={{ padding: '20px' }}>
<h1>My Responsive Dashboard</h1>
<ResponsiveGridLayout
className="layout"
layouts={{ lg: currentLayout }} // Provide current layout for the 'lg' breakpoint
breakpoints={breakpoints}
cols={cols}
rowHeight={30}
onLayoutChange={onLayoutChange}
isDraggable={true}
isResizable={true}
margin={[10, 10]}
containerPadding={[10, 10]}
measureBeforeMount={true} // Set to true for initial measurement if not using SSR
>
<div key="a" style={{ background: '#e0f7fa', border: '1px solid #b2ebf2', padding: '10px' }}>Widget A</div>
<div key="b" style={{ background: '#e8f5e9', border: '1px solid #c8e6c9', padding: '10px' }}>Widget B</div>
<div key="c" style={{ background: '#fff3e0', border: '1px solid #ffe0b2', padding: '10px' }}>Widget C</div>
</ResponsiveGridLayout>
</div>
);
};
export default MyResponsiveDashboard;