まえがき
React で Drag and Drop をしたかったので、atlassian/react-beautiful-dnd を使った。
Trello みたいにヌルヌル dnd できるのですごい。Github Star の伸びも React ライブラリにしてはすごい。
動作重い問題
README.md でも performance の話がちょいちょいあるが、無駄な re-render を防がないと重くなってしまう。
僕が今回実装してみても、はじめ動きがカクカクになってとても使いにくかったので、README.md 参考にパフォーマンス最適化をした。
最適化
Recommended Droppable performance optimisation を参考にした。
ドキュメントのとおり実装してみてもカクカクし続けたけど、下の DraggableListItem.shouldComponentUpdate
を書いてからカクカクしなくなった!
未選択リストと選択中リスト間でitemを移動させるやつ.jsx
class DraggableListItem extends React.Component {
shouldComponentUpdate(nextProps) {
return this.props.index !== nextProps.index; // これ!
}
render() {
return (
<Draggable draggableId={this.props.item.id} index={this.props.index}>
{(provided, snapshot) =>
<li
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
{item.name}
</li>}
</Draggable>
);
}
}
class InnerList extends React.Component {
shouldComponentUpdate(nextProps) {
return this.props.items !== nextProps.items;
}
render() {
const { items } = this.props;
return items.map((item, index) => {
return (
<DraggableListItem
key={item.id}
item={item}
index={index}
/>
);
});
}
}
// DragDropContext の中身
class ItemPicker extends React.Component {
render() {
return (
<>
<div>
<h2>未選択</h2>
<Droppable droppableId="unselected">
{(provided, snapshot) =>
<ul ref={provided.innerRef}>
<InnerList items={this.props.unselectedItemList} />
{provided.placeholder}
</ul>}
</Droppable>
</div>
<div>
<h2>選択中</h2>
<Droppable droppableId="selected">
{(provided, snapshot) =>
<ul ref={provided.innerRef}>
<InnerList items={this.props.selectedItemList} />
{provided.placeholder}
</ul>}
</Droppable>
</div>
</>
);
}
}