Reactのクイズ処理から学ぶ、Promiseとtry…catchの連携メモ
Reactの公式サンプルコードで気になった処理があったので、どのような処理を行なっているかをメモします。
内容は、「問題の答えを送信し、正解か不正解かによって表示する内容を出し分ける」という簡単なクイズアプリ。
表示にはJSXが使われていますが、処理の部分はJavaScript(Promiseやtry…catch)で書かれています。
JavaScript(JSX)のコード
上記のサンプルコードはこちら。
import { useState } from 'react';
export default function Form() {
const [answer, setAnswer] = useState('');
const [error, setError] = useState(null);
const [status, setStatus] = useState('typing');
if (status === 'success') {
return <h1>That's right!</h1>
}
async function handleSubmit(e) {
e.preventDefault();
setStatus('submitting');
try {
await submitForm(answer);
setStatus('success');
} catch (err) {
setStatus('typing');
setError(err);
}
}
function handleTextareaChange(e) {
setAnswer(e.target.value);
}
return (
<>
<h2>City quiz</h2>
<p>
In which city is there a billboard that turns air into drinkable water?
</p>
<form onSubmit={handleSubmit}>
<textarea
value={answer}
onChange={handleTextareaChange}
disabled={status === 'submitting'}
/>
<br />
<button disabled={
answer.length === 0 ||
status === 'submitting'
}>
Submit
</button>
{error !== null &&
<p className="Error">
{error.message}
</p>
}
</form>
</>
);
}
function submitForm(answer) {
// Pretend it's hitting the network.
return new Promise((resolve, reject) => {
setTimeout(() => {
let shouldError = answer.toLowerCase() !== 'lima'
if (shouldError) {
reject(new Error('Good guess but a wrong answer. Try again!'));
} else {
resolve();
}
}, 1500);
});
}
処理の流れ
1. ユーザーがフォームで回答を入力し、「Submit」を押す
<form onSubmit={handleSubmit}>
フォームが送信されると、onSubmit
に登録されたhandleSubmit
関数が呼ばれます。
2. handleSubmit関数(非同期関数)
async function handleSubmit(e) {
e.preventDefault(); // デフォルト動作(フォームの送信)を無効化
setStatus('submitting'); // 送信中ステータスに変更(入力や送信ボタンを制限)
try {
await submitForm(answer); // ここで submitForm の非同期処理が完了するまで待つ
setStatus('success'); // 成功したら成功ステータスに切替
} catch (err) {
setStatus('typing'); // エラーが起きたら入力可能な状態に戻す
setError(err); // エラー情報を保存して画面に表示
}
}
補足:基本的なtry…catchの使い方。
try {
// ここにエラーが起こるかもしれない処理を書く
} catch (error) {
// エラーが起きたときに実行される
}
try
ブロック内のコードが実行され、そこで例外が発生すると、catch
ブロック内のコードが実行されます。
ここで注目すべきはawait submitForm(answer)
の部分です。submitForm
はPromiseを返す非同期関数なので、完了するまで待ちます。
submitForm
で処理に問題なければ正解、エラーが返ってくればcatch
が実行され不正解が表示されるという仕組みです。
3.submitForm 関数(Promise を返す非同期処理)
function submitForm(answer) {
return new Promise((resolve, reject) => {
setTimeout(() => {
let shouldError = answer.toLowerCase() !== 'lima';
if (shouldError) {
reject(new Error('Good guess but a wrong answer. Try again!'));
} else {
resolve(); // 正解時は何も返さず resolve
}
}, 1500); // 1.5秒後に判定
});
}
- 正解は
'lima'
です。 - 不正解ならエラーを発生(
reject()
)。 - 正解なら
resolve()
で完了通知。
不正解の場合、new Error()
でエラーオブジェクトを生成し、handleSubmit
関数のcatch(err)
でその内容を受け取れるようになっています。
補足:基本的なPromise()の使い方。
const promise = new Promise((resolve, reject) => {
// 非同期処理
if (成功) {
resolve(結果); // 成功したときに呼ばれる
} else {
reject(エラー); // 失敗したときに呼ばれる
}
});
なぜPromiseを使って遅延しているのか
実際のWebアプリでは、フォーム送信後にサーバーにデータを送る処理(=非同期通信)が入ります。
おそらく、「サーバーに問い合わせて結果が返ってくるまで時間がかかる」という状況を模擬(シミュレーション)しているのだと思われます。
- フォームの回答を送信
try
ではawait
でPromise
の処理が終わるまで待っているPromise
で処理が完了Promise
でresolve()
が返れば、try
が実行されて正解処理Promise
でreject()
が返れば、catch
が実行されて不正解処理
という具合です。
おすすめWEBスクール
WEB制作やWEBデザインを学びたいなら、SNSでも話題の「デイトラ」がおすすめ!
どのコースも10万円前後と業界最安値で、副業や転職に向けて十分なスキルを身につけることができます。
\ クリックしてジャンプ! /
お気軽にコメントどうぞ