Codex と Claude のレビューで浮かんだ「状態のスナップショット」まわりの観察を、勉強のためにまとめたものです。
ここで言う「web」は、綴ったものを web でも見られるように開発中のアプリ(紡Book)のことです。
綴Photo モバイルのコードレビューで、複数の観点(データ保全・UX・設計)が同じ 1 箇所を指摘した。「写真を web に送る」操作が、画面上は「送信しました」と出るのに、実際にはサーバへ何も送られていない可能性がある、というもの。原因は派手なバグではなく、状態管理では誰でも一度はハマる「古いスナップショットを使ってしまう」型だった。
この記事で扱う観察ポイント
- データベースを更新した「直後」に、画面が持っていた更新前のデータを使うと何が起きるか
- なぜ状態管理ツールを使っていても起きるのか
- 「画面が持っている値」と「データベースの値」のどちらを信じるべきか
コードで起きていたこと
「web に送る」ボタンを押したときの処理は、ざっくりこういう順番だった(変数名などは構造がわかる範囲に置き換えている)。
// 1. データベースの「この写真を web に送る」フラグを true にする
await db.markSelected(item.photo.id, true);
// 2. 送信用のデータを組み立てる
final memory = Memory(
photo: item.photo, // ← これは画面が前から持っていた古い写し
meanings: item.meanings,
);
// 3. 送信する
await sync([memory]);(この「フラグ」は、はい/いいえだけを持つ小さな目印です。電気のスイッチと同じで、true=オン=web に送ります、false=オフ=送りません。)
そして送信側は「フラグが true のものだけ送る」という絞り込みをしていた。
// 送信対象を絞る処理
for (final photo in photos) {
if (!photo.webSelected) continue; // false のものは飛ばす
// ... 送信データに詰める
}さらに悪いことに、送信処理は「0 件成功」を返します。呼び出し側はそれを成功とみなして「送信しました」と表示します。ユーザーから見ると、押した・成功表示が出た・でも何も起きていない、という一番たちの悪い形になります。
なぜそうなりやすいか
「うっかり」ではなく、構造的に誰でもハマります。
普段は自動更新に助けられているぶん、「書いた直後の値はまだ古い」という瞬間が見えにくいです。だから気づきにくいです。
実際、同じアプリの別の画面(設定からの一括送信)では、送信前にデータベースから読み直していて、この問題は起きていなかった。同じ「送信する」処理が 2 箇所にあって、片方だけ正しかった、というのも一緒に見つかっている。
改善の方向
考え方はひとつ。データベースを書き換えたら、その後に使うデータはデータベースから読み直します(fresh read と呼ばれます)。
await db.markSelected(item.photo.id, true);
// 古い写しを使わず、最新をデータベースから取り直す
final memory = await db.fetchMemory(item.photo.id);
await sync([memory]);最小の応急処置としては「写しの該当フラグだけ手で true にした新しい写しを作る」方法もあるが、これは「データベースを読まずに、正解を手で組み立て直している」ことになります。本筋は読み直しのほうだ。
さらに一段引くと、この「フラグを立てる → 読み直す → 送る → 結果を書き戻す」という一連の流れを画面の中にベタ書きせず、ひとつの専用の処理(サービス)にまとめてしまうと、2 箇所で食い違うこと自体がなくなります。
追記(2026-07): このあと実際にその形にした。一連の流れは画面から出して同期の専用サービスへ移してあり、画面側に残したのは結果の表示だけになっている。上に書いた「同じ処理が 2 箇所にあって、片方だけ正しい」状態も一緒に消えた。読み直しも、フラグを立てた直後にデータベースから取り直す形で入っている。
学びポイント
- 同じ処理が 2 箇所にあると、片方だけ正しく書けていて、もう片方がズレていても気づけません。流れごと 1 箇所にまとめると食い違いが消えます。
このテーマの括り
表示が成功に見えるので、テストや手動確認でも見逃しやすいです(写真そのものは消えないので、壊れたと気づけません)。
「保存できた」と「画面の値が最新になった」は別のタイミングだ、という感覚を持っておくと、この種の事故を予防できます。
おわりに
この手の問題は、状態管理ツールに慣れて「値は勝手に最新になる」という安心感が出てきた頃に出やすいです。自動更新への信頼が厚くなるほど、「今この行で書いた値は、まだ画面の写しに乗っていない」という一瞬が視界から外れます。そこを一度でも踏むと、似た落とし穴はまとめて見えるようになります。
この記事は 2026 年 6 月時点の自分の理解で書いています。仕様や認識が変わってる可能性があります。