WEBVTT

1
00:00:00.000 --> 00:00:00.872
こんにちは。

2
00:00:00.872 --> 00:00:02.762
リアクト入門の第三回です。

3
00:00:02.762 --> 00:00:09.011
今回は、ユースリデューサーを使って、状態の更新ルールを一か所へ整理する方法を学びます。

4
00:00:09.011 --> 00:00:13.081
入力値やチェック状態だけなら、ユースステートが便利です。

5
00:00:13.081 --> 00:00:17.587
でも、追加、購入済みの切り替え、削除のように、更新の種類が増えてくると、

6
00:00:17.587 --> 00:00:22.093
更新のたびに処理があちこちへ散らばりやすくなります。

7
00:00:22.093 --> 00:00:26.816
そこで、買い物リストを題材に、ステート、アクション、リデューサーの役割を、

8
00:00:26.816 --> 00:00:31.540
タイプスクリプトのコードで一つずつ確認していきましょう。

9
00:00:31.540 --> 00:00:34.185
まず、三つの言葉の関係を整理します。

10
00:00:34.185 --> 00:00:36.242
ステートは現在のデータです。

11
00:00:36.242 --> 00:00:39.475
この例では、商品の配列がステートになります。

12
00:00:39.475 --> 00:00:42.414
アクションは、何をしたいかを表す値です。

13
00:00:42.414 --> 00:00:47.411
追加したい、切り替えたい、削除したい、といった操作の種類を表します。

14
00:00:47.411 --> 00:00:53.730
リデューサーは、現在のステートとアクションを受け取り、次のステートを計算する関数です。

15
00:00:53.730 --> 00:00:58.432
コンポーネントは、ディスパッチという関数でアクションを渡します。

16
00:00:58.432 --> 00:01:04.751
すると、リデューサーが次のステートを返し、画面は新しいステートから組み立て直されます。

17
00:01:04.751 --> 00:01:09.894
大切なのは、すべての値を一つのリデューサーへまとめなくてよいことです。

18
00:01:09.894 --> 00:01:13.568
入力中の商品名は、別のユースステートで管理します。

19
00:01:13.568 --> 00:01:20.023
更新ルールは、ショッピングリデューサー・ティーエスというファイルにまとめます。

20
00:01:20.023 --> 00:01:23.498
まず、商品の型であるアイテムを定義します。

21
00:01:23.498 --> 00:01:28.629
アイディー、名前、そして購入済みかどうかを示すダンを持ちます。

22
00:01:28.629 --> 00:01:30.780
次に、アクションの型です。

23
00:01:30.780 --> 00:01:34.587
追加のときは商品そのものが必要で、切り替えと削除のときはアイディーが必要だと、

24
00:01:34.587 --> 00:01:38.394
型で表せます。

25
00:01:38.394 --> 00:01:45.179
このように、操作の種類ごとに必要な情報が違う形を、判別可能なユニオン型と呼びます。

26
00:01:45.179 --> 00:01:49.813
初期データは、未購入の牛乳と、購入済みのパンの二件です。

27
00:01:49.813 --> 00:01:56.268
種類を取り違えたアクションを書くと、タイプスクリプトがエラーで教えてくれます。

28
00:01:56.268 --> 00:02:00.873
リデューサー本体は、アクションのタイプで分岐します。

29
00:02:00.873 --> 00:02:06.365
追加では、元の配列を広げて、新しい商品を加えた配列を返します。

30
00:02:06.365 --> 00:02:16.284
切り替えでは、マップで配列をたどり、アイディーが一致した商品だけ、ダンを反転させた新しいオブジェクトを作ります。

31
00:02:16.284 --> 00:02:19.472
一致しない商品は、そのまま使います。

32
00:02:19.472 --> 00:02:24.255
削除では、フィルターで対象以外を残した配列を返します。

33
00:02:24.255 --> 00:02:26.203
実機でも確認しました。

34
00:02:26.203 --> 00:02:34.706
初期は二件で未購入は一件、りんごを追加すると三件になり、牛乳を切り替えると未購入は一件減ります。

35
00:02:34.706 --> 00:02:38.248
削除では、指定した商品だけが消えました。

36
00:02:38.248 --> 00:02:41.968
どの分岐も、元の配列は書き換えていません。

37
00:02:41.968 --> 00:02:45.356
リデューサーを書くときの約束が二つあります。

38
00:02:45.356 --> 00:02:48.745
一つ目は、元のステートを変更しないことです。

39
00:02:48.745 --> 00:02:56.291
プッシュで配列へ追加したり、商品のダンを直接書き換えたりせず、新しい配列やオブジェクトを返します。

40
00:02:56.291 --> 00:03:00.296
変更しない要素は、同じオブジェクトを再利用できます。

41
00:03:00.296 --> 00:03:06.918
二つ目は、同じステートとアクションからは、必ず同じ結果を返す純粋な関数にすることです。

42
00:03:06.918 --> 00:03:14.157
そのため、通信やストレージへの保存、乱数によるアイディー生成は、リデューサーの中に入れません。

43
00:03:14.157 --> 00:03:19.239
アイディーは、後で見るイベント処理で作って、アクションへ含めます。

44
00:03:19.239 --> 00:03:24.630
さらにこの例では、アサートネバーという仕組みで、将来アクションの種類を増やしたのに分岐を書き忘れた場合、

45
00:03:24.630 --> 00:03:30.020
型エラーで気づけるようにしています。

46
00:03:30.020 --> 00:03:34.857
次に、画面側のショッピングリスト・ティーエスエックスを作ります。

47
00:03:34.857 --> 00:03:39.392
ユースリデューサーに、リデューサーと初期データを渡すと、現在のアイテムズと、

48
00:03:39.392 --> 00:03:43.927
アクションを送るディスパッチが返ってきます。

49
00:03:43.927 --> 00:03:48.159
一方、入力中の商品名は、ユースステートで別に保持します。

50
00:03:48.159 --> 00:03:52.694
リストの更新ルールには関係しない、一時的な入力値だからです。

51
00:03:52.694 --> 00:03:58.438
未購入の件数は、専用のステートを作らず、アイテムズをフィルターして数えます。

52
00:03:58.438 --> 00:04:03.880
すでに持っているデータから計算できる値は、描画の中で求めるのが基本です。

53
00:04:03.880 --> 00:04:08.112
保存する値を増やすほど、更新の漏れが起きやすくなります。

54
00:04:08.112 --> 00:04:10.581
操作は、ディスパッチで伝えます。

55
00:04:10.581 --> 00:04:16.444
フォームを送信したら、まず商品名の前後の空白を取り除き、空なら何もしません。

56
00:04:16.444 --> 00:04:21.304
空でなければ、クリプト・ランダムユーユーアイディーで一時的なアイディーを作り、

57
00:04:21.304 --> 00:04:26.164
追加のアクションを送って、入力欄を空に戻します。

58
00:04:26.164 --> 00:04:30.638
この仕組みは、安全な接続の環境で使う点も押さえてください。

59
00:04:30.638 --> 00:04:36.810
チェックボックスが変わったら、切り替えのアクションと商品のアイディーを送ります。

60
00:04:36.810 --> 00:04:40.204
削除ボタンでは、削除のアクションを送ります。

61
00:04:40.204 --> 00:04:46.375
ボタンの読み上げ用の名前には商品名を含めるので、どの商品を消すのかが伝わります。

62
00:04:46.375 --> 00:04:52.084
画面側は、何をしたいかだけを伝え、更新の計算はリデューサーへ任せる形です。

63
00:04:52.084 --> 00:04:55.571
入口のアプリ・ティーエスエックスは、シンプルです。

64
00:04:55.571 --> 00:05:01.568
見出しとショッピングリストを並べるだけで、状態の管理はショッピングリスト側に任せます。

65
00:05:01.568 --> 00:05:06.170
メイン・ティーエスエックスは、バイトのテンプレートのまま使えます。

66
00:05:06.170 --> 00:05:11.052
一覧の行には、配列の位置ではなく、商品のアイディーをキーに指定します。

67
00:05:11.052 --> 00:05:16.630
追加と削除を繰り返しても、購入済みの状態が別の商品へ移らないようにするためです。

68
00:05:16.630 --> 00:05:20.257
今回、記事のコードそのままを、タイプスクリプトの厳密な型チェックにかけ、

69
00:05:20.257 --> 00:05:23.883
エラーがないことを確認しました。

70
00:05:23.883 --> 00:05:28.764
ブラウザー上での実際の描画と操作の確認は、実行環境の制約で未実施です。

71
00:05:28.764 --> 00:05:34.064
その代わり、リデューサーの計算はノード・ジェーエスで実行して確かめています。

72
00:05:34.064 --> 00:05:37.549
動作確認は、記事の手順どおりに進めます。

73
00:05:37.549 --> 00:05:40.686
初期状態は、全二件、未購入一件です。

74
00:05:40.686 --> 00:05:44.346
空欄や、空白だけの商品名は追加できません。

75
00:05:44.346 --> 00:05:49.052
りんごを追加すると全三件になり、入力欄は空になります。

76
00:05:49.052 --> 00:05:53.931
未購入の商品をチェックすると、未購入の数が一つ減ります。

77
00:05:53.931 --> 00:05:57.591
削除ボタンでは、対象の商品だけが消えます。

78
00:05:57.591 --> 00:06:03.865
すべて削除すると、買うものを追加してください、という案内が表示されます。

79
00:06:03.865 --> 00:06:10.836
あわせて、ビルドを実行して、型エラーや読み込みの漏れがないことも確かめましょう。

80
00:06:10.836 --> 00:06:18.504
リデューサーをテストするときは、追加後の件数だけでなく、元の配列が変わっていないことや、

81
00:06:18.504 --> 00:06:26.172
指定したアイディーだけが切り替わることも確認すると、ルールの誤りに気づきやすくなります。

82
00:06:26.172 --> 00:06:28.702
よくある疑問を二つ取り上げます。

83
00:06:28.702 --> 00:06:34.552
一つ目は、ディスパッチを呼んだ直後にステートが変わらないのはなぜか、です。

84
00:06:34.552 --> 00:06:38.347
ディスパッチは、次の描画に向けた更新の依頼です。

85
00:06:38.347 --> 00:06:46.727
呼び出したイベント処理の途中で、今見えているアイテムズという変数が、その場で書き換わるわけではありません。

86
00:06:46.727 --> 00:06:50.205
更新後の表示は、次の描画で確認してください。

87
00:06:50.205 --> 00:06:56.055
二つ目は、ストリクトモードでリデューサーが追加で呼ばれても大丈夫か、です。

88
00:06:56.055 --> 00:06:59.850
開発中は、追加の呼び出しが起きることがあります。

89
00:06:59.850 --> 00:07:08.230
でも、元のステートを変更せず、乱数や通信を含まない純粋な処理なら、商品が二重に追加されることはありません。

90
00:07:08.230 --> 00:07:11.392
純粋さを保つ約束が、ここで効いてきます。

91
00:07:11.392 --> 00:07:12.224
まとめです。

92
00:07:12.224 --> 00:07:20.544
ユースリデューサーは、更新の種類が増えたときに、ステート、アクション、リデューサーで更新ルールを一か所へ集める方法です。

93
00:07:20.544 --> 00:07:25.536
ただし、ユースステートから必ず移行しなければならないわけではありません。

94
00:07:25.536 --> 00:07:30.943
単純な入力値や開閉の状態には、ユースステートのほうが読みやすい場合があります。

95
00:07:30.943 --> 00:07:36.906
更新の種類が増えた、同じルールが複数のイベントに散らばった、更新処理だけを検証したい。

96
00:07:36.906 --> 00:07:41.482
そんな理由が出てきたときに、ユースリデューサーを検討してください。

97
00:07:41.482 --> 00:07:47.999
練習として、購入済みをまとめて削除するアクションを追加し、型と分岐をそろえて書いてみましょう。

98
00:07:47.999 --> 00:07:53.684
次回は、ユースアイディーで、ラベルと説明を入力フォームに関連付ける方法を学びます。

99
00:07:53.684 --> 00:07:54.932
お疲れさまでした。
