react-draggable vs react-grid-layout vs flexlayout-react vs react-flexbox-grid vs react-mosaic-component vs react-split-pane
レイアウト管理
react-draggablereact-grid-layoutflexlayout-reactreact-flexbox-gridreact-mosaic-componentreact-split-pane類似パッケージ:

レイアウト管理

レイアウト管理ライブラリは、Reactアプリケーション内でコンポーネントの配置やサイズを動的に制御するためのツールです。これらのライブラリは、ドラッグ&ドロップ、リサイズ、グリッドシステムなどの機能を提供し、ユーザーがインターフェースをカスタマイズできるようにします。これにより、よりインタラクティブで柔軟なデザインが可能になり、特にダッシュボードやデータビジュアライゼーションアプリケーションにおいて重要です。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
react-draggable4,883,3609,294243 kB2139ヶ月前MIT
react-grid-layout2,002,74522,1141.13 MB772ヶ月前MIT
flexlayout-react01,263522 kB1805日前ISC
react-flexbox-grid02,918-618年前MIT
react-mosaic-component04,731260 kB371年前Apache-2.0
react-split-pane03,373104 kB320日前MIT

機能比較: react-draggable vs react-grid-layout vs flexlayout-react vs react-flexbox-grid vs react-mosaic-component vs react-split-pane

ドラッグ&ドロップ

  • react-draggable:

    react-draggableは、個々のコンポーネントをドラッグ可能にするシンプルなAPIを提供します。

  • react-grid-layout:

    react-grid-layoutは、グリッド内でコンポーネントをドラッグ&ドロップできる高度な機能を提供します。

  • flexlayout-react:

    flexlayout-reactは、フレックスボックスを利用した複雑なレイアウトをサポートし、タブやパネルのドラッグ&ドロップが可能です。

  • react-flexbox-grid:

    react-flexbox-gridは、フレックスボックスを利用したグリッドレイアウトを提供しますが、ドラッグ&ドロップ機能はありません。

  • react-mosaic-component:

    react-mosaic-componentは、モザイクスタイルのレイアウトで、コンポーネントをドラッグして再配置できます。

  • react-split-pane:

    react-split-paneは、パネルを分割し、ユーザーがドラッグしてサイズを調整できますが、コンポーネントの再配置はできません。

リサイズ

  • react-draggable:

    react-draggableは、ドラッグ中にリサイズを行うことはできません。

  • react-grid-layout:

    react-grid-layoutは、グリッド内のコンポーネントをリサイズ可能で、サイズ変更に応じたレイアウト調整が行えます。

  • flexlayout-react:

    flexlayout-reactは、パネルのリサイズをサポートし、レイアウトの柔軟性を提供します。

  • react-flexbox-grid:

    react-flexbox-gridは、リサイズ機能を提供しません。

  • react-mosaic-component:

    react-mosaic-componentは、コンポーネントのリサイズをサポートし、モザイクレイアウトの柔軟性を高めます。

  • react-split-pane:

    react-split-paneは、ユーザーがパネルの境界をドラッグしてリサイズできるシンプルな機能を提供します。

レイアウトの永続化

  • react-draggable:

    react-draggableは、レイアウトの状態を永続化する機能はありません。

  • react-grid-layout:

    react-grid-layoutは、レイアウトの状態を保存し、再配置後も元の状態を保持することができます。

  • flexlayout-react:

    flexlayout-reactは、レイアウトの状態を保存し、再ロード時に復元する機能を提供します。

  • react-flexbox-grid:

    react-flexbox-gridは、レイアウトの永続化機能を提供しません。

  • react-mosaic-component:

    react-mosaic-componentは、レイアウトの状態を管理し、再配置後も元のレイアウトを保持することができます。

  • react-split-pane:

    react-split-paneは、パネルのサイズを永続化する機能はありません。

レスポンシブデザイン

  • react-draggable:

    react-draggableは、レスポンシブデザインをサポートしますが、コンポーネントのサイズや位置は手動で調整する必要があります。

  • react-grid-layout:

    react-grid-layoutは、レスポンシブグリッドレイアウトをサポートし、ウィンドウサイズに応じてコンポーネントの配置を調整できます。

  • flexlayout-react:

    flexlayout-reactは、レスポンシブデザインをサポートし、ウィンドウサイズに応じてレイアウトが調整されます。

  • react-flexbox-grid:

    react-flexbox-gridは、フレックスボックスを利用したレスポンシブグリッドを提供します。

  • react-mosaic-component:

    react-mosaic-componentは、レスポンシブデザインをサポートしますが、モザイクレイアウトの特性上、調整が必要な場合があります。

  • react-split-pane:

    react-split-paneは、レスポンシブデザインをサポートしますが、パネルのサイズは固定されるため、デザインの調整が必要です。

コード例

  • react-draggable:

    react-draggableのコード例

    import React from 'react';
    import Draggable from 'react-draggable';
    
    const DraggableComponent = () => {
      return (
        <Draggable>
          <div style={{ width: '100px', height: '100px', background: 'lightblue' }}>
            ドラッグ可能なコンポーネント
          </div>
        </Draggable>
      );
    };
    
    export default DraggableComponent;
    
  • react-grid-layout:

    react-grid-layoutのコード例

    import React from 'react';
    import GridLayout from 'react-grid-layout';
    
    const layout = [
      { i: 'a', x: 0, y: 0, w: 1, h: 2 },
      { i: 'b', x: 1, y: 0, w: 1, h: 2 },
      { i: 'c', x: 2, y: 0, w: 1, h: 2 },
    ];
    
    const GridLayoutExample = () => {
      return (
        <GridLayout layout={layout} cols={3} rowHeight={30} width={300}>
          <div key="a" style={{ background: 'lightcoral' }}>A</div>
          <div key="b" style={{ background: 'lightblue' }}>B</div>
          <div key="c" style={{ background: 'lightgreen' }}>C</div>
        </GridLayout>
      );
    };
    
    export default GridLayoutExample;
    
  • flexlayout-react:

    flexlayout-reactのコード例

    import React from 'react';
    import { FlexLayout } from 'flexlayout-react';
    
    const layoutConfig = {
      global: {},
      borders: [],
      layout: {
        type: 'row',
        children: [
          {
            type: 'tab',
            name: 'Tab 1',
            component: 'component1',
          },
          {
            type: 'tab',
            name: 'Tab 2',
            component: 'component2',
          },
        ],
      },
    };
    
    const App = () => {
      return <FlexLayout layout={layoutConfig} />;
    };
    
    export default App;
    
  • react-flexbox-grid:

    react-flexbox-gridのコード例

    import React from 'react';
    import { Container, Row, Col } from 'react-flexbox-grid';
    
    const FlexboxGridExample = () => {
      return (
        <Container>
          <Row>
            <Col xs={12} sm={6} md={4}>カラム 1</Col>
            <Col xs={12} sm={6} md={4}>カラム 2</Col>
            <Col xs={12} sm={6} md={4}>カラム 3</Col>
          </Row>
        </Container>
      );
    };
    
    export default FlexboxGridExample;
    
  • react-mosaic-component:

    react-mosaic-componentのコード例

    import React from 'react';
    import { Mosaic, MosaicNode } from 'react-mosaic-component';
    
    const mosaicId = 'mosaic';
    const initialLayout = {
      direction: 'row',
      first: {
        direction: 'column',
        first: 'A',
        second: 'B',
      },
      second: 'C',
    };
    
    const MosaicExample = () => {
      return (
        <Mosaic
          id={mosaicId}
          initialValue={initialLayout}
          renderTile={(id) => <div>{id}</div>}
        />
      );
    };
    
    export default MosaicExample;
    
  • react-split-pane:

    react-split-paneのコード例

    import React from 'react';
    import SplitPane from 'react-split-pane';
    
    const SplitPaneExample = () => {
      return (
        <SplitPane split="vertical" minSize={50} defaultSize={200}>
          <div>左側のパネル</div>
          <div>右側のパネル</div>
        </SplitPane>
      );
    };
    
    export default SplitPaneExample;
    

選び方: react-draggable vs react-grid-layout vs flexlayout-react vs react-flexbox-grid vs react-mosaic-component vs react-split-pane

  • react-draggable:

    react-draggableは、シンプルなドラッグ&ドロップ機能を実装したい場合に最適です。特定のコンポーネントをドラッグ可能にするだけでなく、カスタマイズ可能なイベントハンドラーを提供するため、軽量で柔軟なソリューションが必要なプロジェクトに向いています。

  • react-grid-layout:

    react-grid-layoutは、ドラッグ&ドロップによるグリッドレイアウトの作成と管理を可能にします。特に、ダッシュボードやインタラクティブなインターフェースで、コンポーネントの位置やサイズを動的に変更する必要がある場合に最適です。

  • flexlayout-react:

    flexlayout-reactを選択するのは、複雑なフレックスボックスレイアウトを必要とし、タブやパネルの動的な管理が求められる場合です。特に、レイアウトの状態を保存・復元する機能が必要なアプリケーションに適しています。

  • react-flexbox-grid:

    react-flexbox-gridは、フレックスボックスを利用したレスポンシブなグリッドシステムを提供します。特に、CSSフレームワークに依存せず、簡単にグリッドレイアウトを構築したい場合に適しています。デザインの一貫性を保ちながら、柔軟なレイアウトを実現できます。

  • react-mosaic-component:

    react-mosaic-componentは、モザイクスタイルのレイアウトを作成するためのライブラリです。特に、複雑なレイアウトをタイル状に配置し、ユーザーが自由にリサイズや再配置できるインターフェースを提供したい場合に適しています。

  • react-split-pane:

    react-split-paneは、2つのパネルを分割し、ユーザーがドラッグしてサイズを調整できるようにするコンポーネントです。特に、シンプルな分割ビューを実装したい場合に最適で、コードが簡潔で使いやすいです。

react-draggable のREADME

React-Draggable

TravisCI Build Status Appveyor Build Status npm downloads gzip size version

A simple component for making elements draggable.

<Draggable>
  <div>I can now be moved around!</div>
</Draggable>
VersionCompatibility
4.xReact 16.3+
3.xReact 15-16
2.xReact 0.14 - 15
1.xReact 0.13 - 0.14
0.xReact 0.10 - 0.13

Technical Documentation

Installing

$ npm install react-draggable

If you aren't using browserify/webpack, a UMD version of react-draggable is available. It is updated per-release only. This bundle is also what is loaded when installing from npm. It expects external React and ReactDOM.

If you want a UMD version of the latest master revision, you can generate it yourself from master by cloning this repository and running $ make. This will create umd dist files in the dist/ folder.

Exports

The default export is <Draggable>. At the .DraggableCore property is <DraggableCore>. Here's how to use it:

// ES6
import Draggable from 'react-draggable'; // The default
import {DraggableCore} from 'react-draggable'; // <DraggableCore>
import Draggable, {DraggableCore} from 'react-draggable'; // Both at the same time

// CommonJS
let Draggable = require('react-draggable');
let DraggableCore = Draggable.DraggableCore;

<Draggable>

A <Draggable> element wraps an existing element and extends it with new event handlers and styles. It does not create a wrapper element in the DOM.

Draggable items are moved using CSS Transforms. This allows items to be dragged regardless of their current positioning (relative, absolute, or static). Elements can also be moved between drags without incident.

If the item you are dragging already has a CSS Transform applied, it will be overwritten by <Draggable>. Use an intermediate wrapper (<Draggable><span>...</span></Draggable>) in this case.

Draggable Usage

View the Demo and its source for more.

import React from 'react';
import ReactDOM from 'react-dom';
import Draggable from 'react-draggable';

class App extends React.Component {

  eventLogger = (e: MouseEvent, data: Object) => {
    console.log('Event: ', e);
    console.log('Data: ', data);
  };

  render() {
    return (
      <Draggable
        axis="x"
        handle=".handle"
        defaultPosition={{x: 0, y: 0}}
        position={null}
        grid={[25, 25]}
        scale={1}
        onStart={this.handleStart}
        onDrag={this.handleDrag}
        onStop={this.handleStop}>
        <div>
          <div className="handle">Drag from here</div>
          <div>This readme is really dragging on...</div>
        </div>
      </Draggable>
    );
  }
}

ReactDOM.render(<App/>, document.body);

Draggable API

The <Draggable/> component transparently adds draggability to its children.

Note: Only a single child is allowed or an Error will be thrown.

For the <Draggable/> component to correctly attach itself to its child, the child element must provide support for the following props:

  • style is used to give the transform css to the child.
  • className is used to apply the proper classes to the object being dragged.
  • onMouseDown, onMouseUp, onTouchStart, and onTouchEnd are used to keep track of dragging state.

React.DOM elements support the above properties by default, so you may use those elements as children without any changes. If you wish to use a React component you created, you'll need to be sure to transfer prop.

<Draggable> Props:

//
// Types:
//
type DraggableEventHandler = (e: Event, data: DraggableData) => void | false;
type DraggableData = {
  node: HTMLElement,
  // lastX + deltaX === x
  x: number, y: number,
  deltaX: number, deltaY: number,
  lastX: number, lastY: number
};

//
// Props:
//
{
// If set to `true`, will allow dragging on non left-button clicks.
allowAnyClick: boolean,

// Default `false` and default behavior before 4.5.0.
// If set to `true`, the 'touchstart' event will not be prevented,
// which will allow scrolling inside containers. We recommend
// using the 'handle' / 'cancel' props when possible instead of enabling this.
// 
// See https://github.com/react-grid-layout/react-draggable/issues/728
allowMobileScroll: boolean,

// Determines which axis the draggable can move. This only affects
// flushing to the DOM. Callbacks will still include all values.
// Accepted values:
// - `both` allows movement horizontally and vertically (default).
// - `x` limits movement to horizontal axis.
// - `y` limits movement to vertical axis.
// - 'none' stops all movement.
axis: string,

// Specifies movement boundaries. Accepted values:
// - `parent` restricts movement within the node's offsetParent
//    (nearest node with position relative or absolute), or
// - a selector, restricts movement within the targeted node
// - An object with `left, top, right, and bottom` properties.
//   These indicate how far in each direction the draggable
//   can be moved.
bounds: {left?: number, top?: number, right?: number, bottom?: number} | string,

// Specifies a selector to be used to prevent drag initialization. The string is passed to
// Element.matches, so it's possible to use multiple selectors like `.first, .second`.
// Example: '.body'
cancel: string,

// Class names for draggable UI.
// Default to 'react-draggable', 'react-draggable-dragging', and 'react-draggable-dragged'
defaultClassName: string,
defaultClassNameDragging: string,
defaultClassNameDragged: string,

// Specifies the `x` and `y` that the dragged item should start at.
// This is generally not necessary to use (you can use absolute or relative
// positioning of the child directly), but can be helpful for uniformity in
// your callbacks and with css transforms.
defaultPosition: {x: number, y: number},

// If true, will not call any drag handlers.
disabled: boolean,

// Default `true`. Adds "user-select: none" while dragging to avoid selecting text.
enableUserSelectHack: boolean,

// Specifies the x and y that dragging should snap to.
grid: [number, number],

// Specifies a selector to be used as the handle that initiates drag.
// Example: '.handle'
handle: string,

// If desired, you can provide your own offsetParent for drag calculations.
// By default, we use the Draggable's offsetParent. This can be useful for elements
// with odd display types or floats.
offsetParent: HTMLElement,

// Called whenever the user mouses down. Called regardless of handle or
// disabled status.
onMouseDown: (e: MouseEvent) => void,

// Called when dragging starts. If `false` is returned any handler,
// the action will cancel.
onStart: DraggableEventHandler,

// Called while dragging.
onDrag: DraggableEventHandler,

// Called when dragging stops.
onStop: DraggableEventHandler,

// If running in React Strict mode, ReactDOM.findDOMNode() is deprecated.
// Unfortunately, in order for <Draggable> to work properly, we need raw access
// to the underlying DOM node. If you want to avoid the warning, pass a `nodeRef`
// as in this example:
//
// function MyComponent() {
//   const nodeRef = React.useRef(null);
//   return (
//     <Draggable nodeRef={nodeRef}>
//       <div ref={nodeRef}>Example Target</div>
//     </Draggable>
//   );
// }
//
// This can be used for arbitrarily nested components, so long as the ref ends up
// pointing to the actual child DOM node and not a custom component.
//
// For rich components, you need to both forward the ref *and props* to the underlying DOM
// element. Props must be forwarded so that DOM event handlers can be attached. 
// For example:
//
//   const Component1 = React.forwardRef(function (props, ref) {
//     return <div {...props} ref={ref}>Nested component</div>;
//   });
//
//   const nodeRef = React.useRef(null);
//   <DraggableCore onDrag={onDrag} nodeRef={nodeRef}>
//     <Component1 ref={nodeRef} />
//   </DraggableCore>
//
// Thanks to react-transition-group for the inspiration.
//
// `nodeRef` is also available on <DraggableCore>.
nodeRef: React.Ref<typeof React.Component>,

// Much like React form elements, if this property is present, the item
// becomes 'controlled' and is not responsive to user input. Use `position`
// if you need to have direct control of the element.
position: {x: number, y: number}

// A position offset to start with. Useful for giving an initial position
// to the element. Differs from `defaultPosition` in that it does not
// affect the position returned in draggable callbacks, and in that it
// accepts strings, like `{x: '10%', y: '10%'}`.
positionOffset: {x: number | string, y: number | string},

// Specifies the scale of the canvas your are dragging this element on. This allows
// you to, for example, get the correct drag deltas while you are zoomed in or out via
// a transform or matrix in the parent of this element.
scale: number
}

Note that sending className, style, or transform as properties will error - set them on the child element directly.

Controlled vs. Uncontrolled

<Draggable> is a 'batteries-included' component that manages its own state. If you want to completely control the lifecycle of the component, use <DraggableCore>.

For some users, they may want the nice state management that <Draggable> provides, but occasionally want to programmatically reposition their components. <Draggable> allows this customization via a system that is similar to how React handles form components.

If the prop position: {x: number, y: number} is defined, the <Draggable> will ignore its internal state and use the provided position instead. Alternatively, you can seed the position using defaultPosition. Technically, since <Draggable> works only on position deltas, you could also seed the initial position using CSS top/left.

We make one modification to the React philosophy here - we still allow dragging while a component is controlled. We then expect you to use at least an onDrag or onStop handler to synchronize state.

To disable dragging while controlled, send the prop disabled={true} - at this point the <Draggable> will operate like a completely static component.

<DraggableCore>

For users that require absolute control, a <DraggableCore> element is available. This is useful as an abstraction over touch and mouse events, but with full control. <DraggableCore> has no internal state.

See React-Resizable and React-Grid-Layout for some usage examples.

<DraggableCore> is a useful building block for other libraries that simply want to abstract browser-specific quirks and receive callbacks when a user attempts to move an element. It does not set styles or transforms on itself and thus must have callbacks attached to be useful.

DraggableCore API

<DraggableCore> takes a limited subset of options:

{
  allowAnyClick: boolean,
  allowMobileScroll: boolean,
  cancel: string,
  disabled: boolean,
  enableUserSelectHack: boolean,
  offsetParent: HTMLElement,
  grid: [number, number],
  handle: string,
  onStart: DraggableEventHandler,
  onDrag: DraggableEventHandler,
  onStop: DraggableEventHandler,
  onMouseDown: (e: MouseEvent) => void,
  scale: number
}

Note that there is no start position. <DraggableCore> simply calls drag handlers with the below parameters, indicating its position (as inferred from the underlying MouseEvent) and deltas. It is up to the parent to set actual positions on <DraggableCore>.

Drag callbacks (onStart, onDrag, onStop) are called with the same arguments as <Draggable>.


Contributing

  • Fork the project
  • Run the project in development mode: $ npm run dev
  • Make changes.
  • Add appropriate tests
  • $ npm test
  • If tests don't pass, make them pass.
  • Update README with appropriate docs.
  • Commit and PR

Release checklist

  • Update CHANGELOG
  • make release-patch, make release-minor, or make-release-major
  • make publish

License

MIT