React 入門
JavaScript コメント掲示板アプリの開発
投稿エラー時の処理
新規投稿時に文字数が上限(タイトル10文字,本文15文字)をオーバしたとき,あるいは一方しかデータが入力されていない場合には API 側でエラーの判定が行われます.しかし,エラーになったときにテキストボックスがクリアされてしまう仕様には問題があるかもしれません.この問題を解決するには,API への登録に成功したかどうかを判断して,成功したときだけテキストボックスを空にすればよいだけです.
しかしながら,API への通信が非同期処理であるため考え方が少々難しくなります.具体的には API への非同期の通信が終了するのを待ってから投稿の成否を判定しなければなりません.このためには async
と await
を利用します.
まず,CommentListPage.js の handelCreateFormSubmit
に async
を追加し,その関数の中で axios
の呼び出しに await
を設定します.さらに let
で result
変数を定義し,その関数の最後にその値を返しますが,投稿が成功したときには true
を,失敗した場合には false
を返すようにします.
src/components/CommentListPage.js(抜粋)
const handelCreateFormSubmit = async (title, body) => {
...
let result = false;
const url = "http://127.0.0.1:8000/comments/";
await axios
.post(url, {
title: title,
body: body,
})
.then(res => {
handleCommentsListChange(url);
result = true;
})
.catch(err => {
setResults(results); // 画面を元に戻す(元の配列で更新)
alert("投稿エラー!未入力または文字数超過です.");
});
return result;
...
次に CreateForm.js にも async
と await
を追加します.
src/components/CreateForm.js(抜粋)
const handleSubmit = async (event) => {
event.preventDefault(); // ページ遷移しないように
const result = await props.onSubmit(title, body);
console.log('result', result);
setTitle(''); // 入力フォームを空に戻す
setBody(''); // 入力フォームを空に戻す
inputTitleRef.current.focus(); // フォーカスを当てる
}
これによって,空欄や文字数制限で登録処理に失敗すると,メッセージ画面を閉じた直後に false が出力され,登録処理に成功すると直後に true が表示されます.(async
と await
を削除したときにどのタイミングでどのような結果が表示されるかも合わせて確認するとより理解が深まるでしょう.)
したがって,テキストボックス空に戻す処理に条件分岐を加えるだけで良いでしょう.
src/components/CreateForm.js(抜粋)
const handleSubmit = async (event) => {
event.preventDefault(); // ページ遷移しないように
const result = await props.onSubmit(title, body);
if (result) {
setTitle(''); // 入力フォームを空に戻す
setBody(''); // 入力フォームを空に戻す
}
inputTitleRef.current.focus(); // フォーカスを当てる
}
実際にブラウザで動作を確認します.タイトル(上限10文字)や本文(上限15文字)に上限を超える長い文字列を入力して投稿します.
React で内部的には登録ができて画面上に表示されましたが,文字数が上限を超えているので API 側では登録できず,次のようなエラーメッセージが表示されます.しかし,まだこの段階では CommentListPage.js の handelCreateFormSubmit
関数の処理が終わっていないので,CreateForm.js の handleSubmit
関数では,const result = await props.onSubmit(title, body);
に値が帰ってきていない状態です.したがって,次の行の console.log('result', result);
がまだ実行されておらず,ブラウザのコンソールに結果が出力されていません.
上の画面で「OK」ボタンを押した直後に中断していた処理が再開され,ブラウザのコンソール結果が出力されました.同時に,タイトルや本文のテキストボックスはクリアされず,タイトルにフォーカスが当たりました.