ReduxにおけるコンポーネントでのThunk実行結果の表示
前回のレッスンでは、thunk addProduct を使用してPOSTリクエストを送信しました。
今回は、その実行結果をコンポーネントに表示してみましょう。
商品管理アプリケーションを開き、新しい商品の追加を担当するコンポーネントである
NewProductForm.jsx ファイルを開きます。インポート文を見てみましょう。
アクション productAdded のインポートを thunk addProduct のインポートに置き換えます:
import { addProduct } from './productsSlice'
スライスでリクエストの 'pending' ステータスを追跡していないため、
ユーザーが商品保存ボタンを一度だけ押せるようにしましょう。同じリクエストの重複を防ぐためです。
これを行うために、別のローカルステートを追加します:
const [requestStatus, setRequestStatus] = useState('idle')
次に、ハンドラーの後、関数 onSaveProductClick の前に、
フォームのすべてのフィールドが入力されているか、およびリクエストステータスが 'idle' であるかを確認するコードを書きます:
const canBeSaved =
[name, desc, price, amount, sellerId].every(Boolean) &&
requestStatus === 'idle'
次に、onSaveProductClick のコードを変更します。
まず、これは非同期関数となり、上記の条件が満たされている場合にのみ実行されます:
const onSaveProductClick = async () => {
if (canBeSaved) {}
}
スライスで 'rejected' ステータスを追跡していなくても、
コンソールにエラーを出力することは可能です。そのためには
try-catch 構文を使用します。
また、リクエスト実行後にローカルステートを再度 'idle' に設定するために、
finally も追加します:
const onSaveProductClick = async () => {
if (canBeSaved) {
try {
} catch (err) {
console.error('商品の保存エラー: ', err)
} finally {
setRequestStatus('idle')
}
}
}
catch と finally ブロックについては理解できたので、
try ブロックのコードを書きましょう。
ここでは、thunkの実行結果として何らかのレスポンスが返ってくるまで
ローカルのステータスを 'in progress' に設定し、
その後 thunk addProduct をディスパッチします。
RTK が返すプロミスに追加する関数 unwrap を使用すると、
レスポンスのタイプに応じて try-catch 構文を利用できます。
その後、リクエストが成功した場合は、
ローカルステートを初期状態に戻します。
onSaveProductClick の完全なコードは次のようになります:
const onSaveProductClick = async () => {
if (canBeSaved) {
try {
setRequestStatus('in progress')
await dispatch(
addProduct({ name, desc, price, amount, seller: sellerId })).unwrap()
setName('')
setDesc('')
setPrice(0)
setAmount(0)
setSellerId('')
} catch (err) {
console.error('商品の保存エラー: ', err)
} finally {
setRequestStatus('idle')
}
}
}
アプリケーションを起動し、新しい商品を追加してみましょう。 リクエストが成功すると、フィールドがクリアされ、 新しい商品が商品リストに追加されることが確認できます。 また、ブラウザの Redux DevTools を開き、 タブを切り替えてアクションやステートの変化を確認してください。
生徒管理アプリケーションを開いてください。
その中の NewStudentForm.jsx ファイルを開きます。
別のローカルステート requestStatus を追加し、
初期値を 'idle' に設定してください。
レッスンの内容を参考に、変数 canBeSaved を定義し、
requestStatus の値とフィールドの入力状況に応じて
新しい生徒データを保存するボタンの有効/無効を制御してください。
onSaveStudentClick の非同期コードを記述してください。
このコードは状況に応じて requestStatus の値を変更し、
新しい生徒データで thunk addProduct(訳注: 原文ママ。addStudentと思われる) をディスパッチし、
リクエストが成功した場合はフィールドをクリアし、
失敗した場合はエラーをコンソールに出力するようにします。
レッスンで示したように、try-catch 構文と
RTK の unwrap 関数を使用してください。
アプリケーションを起動し、新しい生徒を追加して、 すべてが正常に動作することを確認してください。