UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【React】react-beautiful-dndというドラッグ&ドロップ用のライブラリを知った

react-beautiful-dnd というドラッグ&ドロップのためのライブラリを知ったので調べた

github.com

react-beautiful-dndは、Atlassian社によって開発されているドラッグ&ドロップのためのライブラリで、使いやすいAPIを提供している

特徴

  1. 使いやすい
    • 直感的なAPI:
      • DragDropContext, Droppable, Draggableという3つの主要コンポーネントを使用するだけで、基本的な機能を実装できる
      • これらのコンポーネントは、実際のUIの構造に沿って自然にネストできる
    • 宣言的な設計:
      • Reactの宣言的なパラダイムに沿った設計になっており、命令的なコードを書く必要がない
      • ドラッグ操作の結果は、onDragEndコールバックで処理するだけで済む
    • センサブルなデフォルト設定:
      • だいたい追加の設定なしで見栄えの良いドラッグアンドドロップUIを実現できる
      • 必要に応じて、細かいカスタマイズも可能
    • 豊富なドキュメントとサンプル:
      • 公式ドキュメントが充実しており、多くの使用例やベストプラクティスが提供されている
  2. アクセシビリティへの配慮
    • キーボード操作のサポート:
      • マウスだけでなく、キーボードを使用してドラッグアンドドロップ操作を行える
      • 矢印キーでの移動、スペースキーでの選択など、直感的な操作が可能
    • スクリーンリーダーのサポート:
      • ドラッグアンドドロップ操作中に、適切なARIA属性が動的に更新される
      • これにより、スクリーンリーダーユーザーにも操作の状況が伝わる
    • 色のコントラスト:
    • フォーカス管理:
      • ドラッグ操作中のフォーカス管理が適切に行われ、キーボードユーザーが操作を追跡しやすくなっている
  3. パフォーマンスの最適化
    • 仮想化のサポート:
      • 大量のアイテムを扱う場合でも、ウィンドウに表示されている部分のみをレンダリングする「仮想化」をサポートしている
      • これにより、メモリ使用量とレンダリング時間を大幅に削減できる
    • スマートな再レンダリング:
    • CSS-in-JSの最適化:
      • スタイリングにCSS-in-JSを使用しているが、パフォーマンスを考慮した実装になっている
      • 動的に変更が必要なスタイルのみをJSで制御し、それ以外はスタティックなCSSとして扱う
    • ブラウザのネイティブイベントの利用:
      • ドラッグ操作の検出やトラッキングに、ブラウザのネイティブイベントを効率的に利用している
      • これにより、スムーズな動作と低いCPU使用率を実現している
    • メモ化とキャッシング:
      • 内部的に適切なメモ化とキャッシングを行い、不要な計算を避けている
      • 特に、ドラッグ中の位置計算などで効果を発揮する

主要コンポーネントの説明

以下のコンポーネントをimportして使う

  <DragDropContext onDragEnd={this.onDragEnd}>
    {/* 子コンポーネント */}
  </DragDropContext>
  • Droppable
    • アイテムをドロップできる領域を定義するコンポーネント
      • droppableIdpropsを必須とし、ドロップ可能な領域を一意に識別する
      • 関数として子コンポーネントを受け取り、ドラッグ状態に関する情報を提供する
      • typepropsで、特定のDraggableのみを受け入れるように設定できる
<Droppable droppableId="list">
  {(provided, snapshot) => (
    <div
      ref={provided.innerRef}
      {...provided.droppableProps}
    >
      {/* Draggableコンポーネント */}
      {provided.placeholder}
    </div>
  )}
</Droppable>
  • Draggable
    • ドラッグ可能な個々のアイテムを定義するコンポーネント
      • draggableIdindexprposを必須とし、アイテムを一意に識別し、順序を管理する
      • 関数として子コンポーネントを受け取り、ドラッグ状態やスタイルに関する情報を提供する
      • isDragDisabledpropsで、特定の条件下でドラッグを無効にできる
<Draggable draggableId={item.id} index={index}>
  {(provided, snapshot) => (
    <div
      ref={provided.innerRef}
      {...provided.draggableProps}
      {...provided.dragHandleProps}
    >
      {item.content}
    </div>
  )}
</Draggable>