React + TypeScriptで「保存ボタンを2回押さないと動かない」問題を解決した方法
はじめに
React + TypeScript を使ってプロダクト改善をしていたとき、
「保存ボタンを 1 回押しただけじゃ保存されない…?」「2 回押さないと動かない…?」という、ちょっと不思議な現象に遭遇しました。
「なんで動かないの…?」と悩んだことがある方、きっと多いんじゃないかなと思います。
私も最初は首をかしげながら原因を探していましたが、調べたり試したりするうちに、だんだんと原因と直し方が見えてきました。
この記事では、初心者なりの視点でその気づきや対処法をまとめています。
同じようなモヤモヤを感じている方に、少しでもヒントになれば嬉しいです!
1. 非同期関数をちゃんと待ってなかった!
checkInput();
await sendForm();
これの何がダメ?
もし checkInput()
が async
関数なら、await
をつけないと完了を待たずに sendForm()
が動き出しちゃいます。
つまり、「入力チェックしてから保存したい」のに、まだチェックが終わってないうちに保存が始まってしまうんです。これだと 1 回目の保存が失敗して、「あれ、もう一度押さないとダメなの?」となることに…。
こう直しました!
await checkInput();
await sendForm();
ただ await
を追加しただけで、保存動作に改善が見られました!
しかし...まだまだ他にも原因が潜んでいそうです...解説しております。続きをご覧ください!!
2. 初期表示で「✖」が出るのはなぜ?
const isCorrect = isChecking ? false : result === expected;
これだと何が起きる?
まだ何も操作していないのに、画面に「✖」が出てしまいます。ユーザーからすると「えっ、間違ってるの!?」と混乱してしまいますよね。
こう変えてみました!
const isCorrect = !hasChecked ? true : isChecking ? false : result === expected;
「まだチェックしてないなら正解扱い」とすることで、いきなりの「✖」表示を避けることができました!
3. 実行チェックが複数走っても困らないように!
await validateCode();
これ、何回も呼ばれると?
ボタンを何度もクリックされたときやトリガーが複数存在する場合に、validateCode()
がそのたびに動いてしまいます。そうすると、API が何度も呼ばれて負荷がかかったり、結果が混ざってしまったりと、思わぬバグの原因になります。
対策してみました!
if (isChecking) return;
isChecking = true;
await validateCode();
isChecking = false;
「いま実行中ならスキップする」ようにして、実行チェックが複数回走らないようにガードを入れました!
4. 出力が一致しないって言われるけど…?
なんで?
出力結果を useState
に入れてから比較しようとすると、ステートの更新タイミングと比較処理がズレてしまって、意図しない判定結果になることがあります。
こうしました!
const cleaned = output.trim();
if (expected && cleaned !== expected) {
toast({ title: "出力が一致しません", status: "error" });
return;
}
ステートに頼らず、その場で値を直接比較することで、ズレによるミス判定を防げました!
5. セッションが切れてても動いちゃってる?
なぜ問題?
ログイン状態が切れていたり、セッション情報がまだ取得できていないときに処理を実行すると、API から空のレスポンスが返ってきたり、想定外の動作になることがあります。(※この例では、サンドボックス環境へアクセスしようとしている想定です。)
防ぐ方法は?
if (!isSessionReady) {
console.error("セッションが無効です");
return;
}
セッションがちゃんと準備できているかを実行直前にチェックするだけで、そういった問題をぐっと減らすことができました!
まとめ
-
await
を忘れずに使おう(非同期処理はちゃんと待つ) - 初期表示で「✖」が出ないようにしよう(ユーザーにやさしく)
- 実行チェックが複数走らないようにしよう(ガードが大事)
- 出力の比較はその場でやろう(ステートに頼りすぎない)
- セッションの状態を事前に確認しよう(空レスポンス回避)
小さな改善でしたが、ちょっとした工夫でかなり快適なフォームになったと思います。もし「保存ボタン押しても反応しないんだけど!?」という現象に困っていたら、少しでも参考になればうれしいです!
ここまで読んでくださってありがとうございました 😊
Discussion