神戸学院大学 経営学部 林坂ゼミ

React 入門トップページ

« 戻る 次へ »

React 入門

TypeScript コメント掲示板アプリの開発

投稿エラー時の処理

新規投稿時に文字数が上限(タイトル10文字,本文15文字)をオーバしたとき,あるいは一方しかデータが入力されていない場合には API 側でエラーの判定が行われます.しかし,エラーになったときにテキストボックスがクリアされてしまう仕様には問題があるかもしれません.この問題を解決するには,API への登録に成功したかどうかを判断して,成功したときだけテキストボックスを空にすればよいだけです.

しかしながら,API への通信が非同期処理であるため考え方が少々難しくなります.具体的には API への非同期の通信が終了するのを待ってから投稿の成否を判定しなければなりません.このためには asyncawait を利用します.

まず,CommentListPage.tsx の handelCreateFormSubmitasync を追加し,その関数の中で axios の呼び出しに await を設定します.さらに letresult 変数を定義し,その関数の最後にその値を返しますが,投稿が成功したときには 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 関数にも asyncawait を追加し,投稿処理結果に応じて入力フォームを空に戻すかどうかを決定するようにします.

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 への登録に失敗したコメントがすでに一覧のリストに表示されています.

ts-2024-46

メッセージ画面を閉じた直後に CommentListPage.tsx で例外処理 .catch によってコメント一覧が投稿前の状態に戻されます.

ts-2024-47

タイトルや本文を短く修正して投稿すると無事に登録できました.

ts-2024-48

目次に戻る