📍

Next.js で supabase の DB と ストレージ画像情報の紐付け(削除時)

2022/03/06に公開

やること

前回: Next.js と supabase の 画像 CRUD 処理を考えるからの続き

Next.js で supabase の DB とストレージを利用した際に、DB データを id 選択で削除するタイミングで、ストレージの画像も削除する

URL オブジェクト(Blob)の扱い

DB にはストレージに入っている画像オブジェクトがある場所への参照パスが入っているが、DBデータを削除してもストレージはそのままの状態。
該当ストレージに対して、Bucket下のパスを「xxxxxxxxxxx/yyyyy」で指定して.removeしないと削除されない。

公式ドキュメント: supabase storage -Delete Fileの下記を使用

const { data, error } = await supabase
  .storage
  .from('avatars')
  .remove(['folder/avatar1.png'])

パスの整形

画像一覧をステートに持たせて表示で使うので、その時に削除で使うパスもステートに持たせる。

const [photos, setPhotos] = useState([]) // 画像一覧をステートで管理

  // 画像情報を DBから取得
  const fetchPhotos = async () => {
    // supabase DB photos のデータをすべて取得
    let { data: photos, error } = await supabase.from('photos').select('*').order('id', true)
    if (error) console.log('error', error)
    // URLオブジェクトにする時用のパスに整形
    for (let i = 0; i < photos.length; i++) { 
      let path = photos[i].url.replace('https://XXXXXXXXXXXXXXXXX.supabase.co/storage/v1/object/public/photos/', '') // publicURLの必要な部分だけ使う
      photos[i].path = path // ←削除の時に使うパス
      let { data, error } = await supabase.storage.from('photos').download(path)
      // URLオブジェクト化した変数を配列 photos の url にして格納
      let objURL = URL.createObjectURL(data)   
      photos[i].url = objURL
      setPhotos([...photos])
    }
  }  
 

削除用のクリックイベントで、id と パスを引数に渡す

ステートの photos 配列にある id と パスを使う。

// view 部分 
 <ul>
   {photos.map((photo) => (
      <li>
         <Image key={photo.id} className='w-4/12' src={photo.url} alt="image" width={150} height={100} layout='fixed' objectfit={"cover"} />
          <button onClick={() => deletePhoto(photo.id,photo.path)} className='border-gray-300 border-2 rounded p-1 w-12'>削除</button>
       </li>
    ))}
</ul>

ストレージの画像削除

// DB から画像情報の削除 deletePhoto 関数の中で(id, path を受け取る)、ストレージの画像削除関数を呼ぶ
  const deleteStoragePhoto = async (path) => {
      await supabase
      .storage
      .from('photos') 
      .remove([path])
  }

プレビュー画像について

新規画像を作成し、送信する前のプレビュー画像がある場合、データをそのまま(postとは別に) photos ステートの配列に持たせる場合は、post前の情報を持つことになるので id がなく、削除選択しても id は undefined になる。
現状は再レンダリングさせて id が入った状態に実装しているが、見た目があまり良くないので将来的に変更するかも。

削除用の supabase ポリシーについて

自分専用のフォルダ配下に挿入・更新・削除できるようにポリシーも設定。
「Get started quickly」で簡単に設定できる。

「Give users access to only their own a top level folder named as uid」を選択。(uidの名前で設定したトップレベルのフォルダーにだけユーザーがアクセスできるようにする)

該当項目を選択(INSERT, UPDATE, DELETE)

まとめ

DB と ストレージの連携についてはあまり参考記事を見つけられずに、途中から我流になってしまったので、正直ベストなやり方は他にありそう。仕上げていく段階でリファクタリングしていきたい。

Discussion