🔀
React(dnd-kit) & Railsで画像の並び替え
何がしたかったのか、したくなかったのか
- 画像の登録や並び替えや削除をしたい
- でも登録や削除や並び替えの際に毎回serverにリクエストを送りたくない
- 更新ボタンを押す等、一回のリクエストで済ませたい
技術調査
まず最初に見つけたのがこのライブラリ
上記のライブラリで実装したサンプルがあったので挙動を確認
1列だけだと正常に動作するのですが、2列になると動作がおかしくなる。。。
ということが判明。
将来的にwrapはsupportされない、つまり2列目がおかしくなる挙動はライブラリ側で直してくれないことが判明。
以下のライブラリが良いという情報を入手、
だが将来的に廃止になることが判明
上記のreact-sortable-hocと同じ作者が精力的に現在作ってるライブラリを発見。
めっちゃいい感じだったのライブラリだったので
dnd-kitを使うことに決定😊
概観(client - json - api)
client
id?でidがない場合も許容しているのは、clientが新しく追加したばかりの画像にはidがないためです(dbで採番しているため)
type Image {
id?: number
image: string
position: number
itemKey: string
}
json
どんなデータをやり取りするのか
{
"item": {
"name": "商品名xxx"
"images": {
"id": 12489,
"image": "blob data xxxx....",
"position": "1",
},
{
"image": "blob data xxxx....",
"position": "1",
}
}
}
api
class Admin::Items::UpdateService < ActiveInteraction::Base
string :name, default: nil
integer :id, default: nil
array :images, default: []
validates :name, presence: true
def execute
ActiveRecord::Base.transaction do
item = Item.find(:id)
item.images.each do |image|
# clientから送られてきたimages(json画像リスト)にあって、
# itemに紐づくitem.images(db画像リスト)ないやつは
next if images.pluck(:id).include?(image.id)
# 削除する
image.destroy!
end
images.each do |image|
exist_image = item.images.to_a.find { |i| i.id == image[:id] }
if exist_image
# dbにすでに存在する画像はpositionのみ更新する
exist_image.update!(position: image[:position])
else
# dbにないやつは作成
item_image = item.images.build(position: image[:position])
item_image.image.attach(data: image[:image])
item_image.save!
end
end
item
end
rescue ActiveRecord::RecordInvalid => e
errors.merge!(e.record.errors)
end
end
かなりざっくりの説明になってしまいましたが、こんな感じでやりたいこと
- 画像の登録や並び替えや削除をしたい
- でも登録や削除や並び替えの際に毎回serverにリクエストを送りたくない
- 更新ボタンを押す等、一回のリクエストで済ませたい
が実現できました🎉
小話
dnd-kitのissueで少しだけ貢献することができました!!
スタンプ初めてもらってすごく嬉しかったです!
ではまた明日!
Discussion