React 入門
TypeScript コメント掲示板アプリの開発
投稿エラー時の処理
新規投稿時に文字数が上限(タイトル10文字,本文15文字)をオーバしたとき,あるいは一方しかデータが入力されていない場合には API 側でエラーの判定が行われます.しかし,エラーになったときにテキストボックスがクリアされてしまう仕様には問題があるかもしれません.この問題を解決するには,API への登録に成功したかどうかを判断して,成功したときだけテキストボックスを空にすればよいだけです.
しかしながら,API への通信が非同期処理であるため考え方が少々難しくなります.具体的には API への非同期の通信が終了するのを待ってから投稿の成否を判定しなければなりません.このためには async
と await
を利用します.
まず,CommentListPage.tsx の handelCreateFormSubmit
に async
を追加し,その関数の中で axios
の呼び出しに await
を設定します.さらに let
で result
変数を定義し,その関数の最後にその値を返しますが,投稿が成功したときには true
を,失敗した場合には false
を返すようにします.
src/components/CommentListPage.tsx(抜粋)
const handelCreateFormSubmit = async (title: string, body: string):Promise<boolean> => {
const newComments = [...results.results]; // スプレッド構文でコメントの配列だけを取り出す
newComments.unshift({ // unshift で先頭に追加,push では最後に追加
id: Date.now(),
title: title,
body: body,
updated_at: "2024-03-18T12:00:00",
});
const newResults = {
"count": results.count + 1, // コメント数は1増やす
"previous": results.previous,
"next" : results.next,
"results": newComments, // これがコメントの配列
};
setResults(newResults); // 画面を更新
let result:boolean = 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 に渡された onSubmit
へ非同期処理の結果を Promise オブジェクトとして返すことになるため,インターフェースを修正します.
src/components/CreateForm.tsx(抜粋)
interface CreateFormProps {
onSubmit: (title: string, body: string) => Promise<boolean>;
}
次に CreateForm.tsx の handleSubmit
関数にも async
と await
を追加し,投稿処理結果に応じて入力フォームを空に戻すかどうかを決定するようにします.
src/components/CreateForm.tsx(抜粋)
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const result = await props.onSubmit(title, body);
if (result) {
setTitle(''); // 入力フォームを空に戻す
setBody(''); // 入力フォームを空に戻す
}
if (inputTitleRef.current) {
inputTitleRef.current.focus(); // フォーカスを当てる
}
};
これによって,空欄や文字数制限で API への登録処理に失敗すると次のようなエラーメッセージが表示されます.エラーメッセージが表示されている段階では API への登録に失敗したコメントがすでに一覧のリストに表示されています.
メッセージ画面を閉じた直後に CommentListPage.tsx で例外処理 .catch
によってコメント一覧が投稿前の状態に戻されます.
タイトルや本文を短く修正して投稿すると無事に登録できました.