Closed4

react-beautiful-dnd ドラッグ&ドロップで順序を入れ替える

バイヤンバイヤン

<DragDropContext />

ドラッグできる要素とドロップできる範囲を指定する。
最上位に置くこと。

onDragEnd

onDragEnd関数を設定してドロップ後のリスト内のアイテムの順番を保持する。

<Droppable />

ドラッグした要素をドロップする範囲を指定する。
指定した範囲外にドロップした場合は順序は入れ替わらない。

droppableId

ライブラリが特定のDroppableインスタンスを追跡できるように追加する必要がある。
string型で指定する。

provided

provided引数を渡す関数をラップする必要があり、引数の値を元にどの要素がどの位置に移動されたかをトラッキングする。

snapshot

ドラッグ&ドロップ中のコンポーネントの状態を返してくれるもの。
プロパティは以下を持っている。

  • isDraggingOver
  • draggingOverWith
  • draggingFromThisWith
  • isUsingPlaceholder

<Draggable />

ドラッグしたい要素をラップする。

draggableId

ライブラリが特定のDraggableインスタンスを追跡できるように追加する必要がある。
string型で指定する。

snapshot

プロパティは以下を持っている。

  • isDragging
  • isDropAnimating
  • dropAnimation
  • draggingOver
  • combineWith
  • combineTargetFor
  • mode

placeholder

Droppableの下に{provided.placeholder}を追加する。
追加することでドラッグしたアイテムがドラッグされる前に使っていたスペースを埋めてくれる。

バイヤンバイヤン

Table内で使用する場合

Table内でreact-beautiful-dndを使用する場合は注意が必要である。
TableRowをドラッグした際のデザインが崩れてしまう可能性がある。
理由は元々の親要素からスタイルが外れてしまう可能性があるからである。
今回は実際にドラッグ中にスタイルが崩れてしまったので、解決策を記録しておく。

開発環境

  • material-ui v4
    • Table
  • react-beautiful-dnd v13.1.0

解決策

親要素からスタイルが外れてしまうため、TableHeadのTableRow配下にあるTableCellの横幅をそれぞれ取得して、その横幅をTableBodyのTableRow配下にあるTableCellにそれぞれ横幅をセットすると崩れなくなる。

const [cellWidthList, setCellWidthList] = useState<number[]>([]);

const updateCellWidth = () => {
  const rowElm = document.getElementById("{TableHeadのTableRowのID}"); // table-head-rowなど
  if (!rowElm) return;
  
  const rowChildren = rowElm.children;
  const result = [];  // number[]
  rowChildren.forEach((child) => {
    result.push(child.clientWidth);
  })
  setCellWidthList(result);
};

cellWidthListを配列順にTableBodyのTableRow配下にあるTableCellにセットすればOK!!

##レスポンシブ対応
上記の解決策でスタイルが崩れることがなかったが、レスポンシブ対応を含めると以下のコードも必要である。

useEffect(() => {
  updateCellWidth();
  
  window.addEventListener('resizeMainArea', updateCellWidth);
  return () => window.removeEventListener('resizeMainArea', updateCellWidth);
},[]);
このスクラップは2024/01/21にクローズされました