はじめに
supabaseのデータをアプリから削除する実装をする際、削除後のデータを表示する方法でつまずいたため内容を共有します。
「修正前」
以下のように記述していました。
const onClickDelete = async (id) => { // idの中にrecord.idが入っている。ここの名称は何でもよい
const deleteData = await deleteTodo(id);
setRecords(deleteData); // ← 原因の場所
};
<button className="delete-button" onClick={() => onClickDelete(record.id)}>
削除
</button>
deleteTodo関数はSupabaseから指定されたidのデータを削除してその結果(削除されたデータ)を返しますが、返ってくるdataは削除されたレコードのみ。
setRecords(deleteData)だと、削除前のrecordsデータから該当のIDだけを取り除く処理が行われず、データ全体が上書きされてしまう。よって、削除しようとした該当データだけ残り、その他が消えてしまう症状が発生していました。
「修正後」
const onClickDelete = async (id) => {
const deleteData = await deleteTodo(id);
setRecords((prevRecords) => prevRecords.filter((records)=> records.id !== id))
};
filterを使ってidが一致しないレコードだけを残す新しい配列を作成する。
ReactでuseStateを使う場合は、状態の更新を行うために「直前の状態」を関数形式で参照しつつ、新しい状態を返す必要があるようです。
filterメソッドは条件に一致する要素だけを残すためのメソッドですが、recordsという関数や条件が指定されていない引数を渡していると、エラーになります。
なお、prevRecordsはReactのuseStateのsetState関数内で使われる引数であり、直前の状態(state)を自動的に参照するためのものです。
ReactのuseStateのsetState関数に関数を渡すと、その関数の引数には「直前のstate」が渡されます。
なお、Reactが自動的にその引数に直前の状態を代入してくれるため、prevRecordsという名前をあらかじめ定義する必要はないみたいです。
以上で意図した挙動になってくれました。
「参考」
const onClickDelete = async (recordId) => {
const deleteData = await deleteTodo(recordId);
setRecords((prevRecords) => prevRecords.filter((records)=> records.id !== recordId))
};
上記のようにidを別の名称にしても良い。onClickDelete(record.id)からrecord.idが渡ってきているので名称を変更しても中身は同じです。
参考資料
JISOUのメンバー募集中!
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてくださ!
▼▼▼