はじめに
登録した内容を編集できる機能を実装した際、保存時にデータが再取得されて順番が入れ替わる問題が発生したので、解決した方法をまとめます。
問題
学習内容を登録後、内容を編集すると登録した順番が入れ替わる。
原因
更新後(保存後)にfetchTodos()
を呼んでいて、Supabase から再取得したデータが順序保証のない状態で返ってきているのが原因でした。
解決方法
Supabase側でcreated_at
を追加し、登録日時で順番を制御する手も考えましたが、手間がかかりそうだったので id 一致要素だけ差し替えるローカル更新で編集成功時に**差し替え(上書き)**だけ行い、再取得をしないようにして配列の順序を維持しました。
データ再取得用
useEffect(() => {
fetchTodos();
}, []);
before
const updateRecordCore = async (
id: string,
values: LearningFormValues
): Promise<boolean> => {
const { records, time, remark } = values;
setIsLoading(true);
const result = await updateHistory(id, records, time!, remark);
if (result !== undefined) {
await fetchTodos();
resetFormState();
setIsLoading(false);
return true;
// 以降エラー処理
after
const updateRecordCore = async (
id: string,
values: LearningFormValues
): Promise<boolean> => {
const { records, time, remark } = values;
setIsLoading(true);
const result = await updateHistory(id, records, time!, remark);
if (result !== undefined) {
// 以下のように修正
setHistoryRecordss((prev) => prev.map((r) => (r.id === id ? result : r)));
resetFormState();
setIsLoading(false);
return true;
// 以降エラー処理
map
└ 配列全体をコピーしつつ、対象だけを差し替える、不変更新の王道パターン。
条件式 (r.id === id ? result : r)
└ id が一致した要素はr = result
に置き換え、それ以外はそのまま返す。
おわりに
関数型アップデートのいい復習になりました。