WEBVTT

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

2
00:00:01.006 --> 00:00:03.186
リアクト入門の第九回です。

3
00:00:03.186 --> 00:00:09.558
今回は、カスタムフック、ユーストグルで、開閉状態を再利用する方法を学びます。

4
00:00:09.558 --> 00:00:15.427
題材は、開いているか閉じているかという、とても単純な真偽値の状態です。

5
00:00:15.427 --> 00:00:23.811
メニューの開閉、説明欄の展開、フィルターの表示切り替えなど、画面のあちこちで同じ形の処理が現れます。

6
00:00:23.811 --> 00:00:32.363
そのたびに同じコードを書く代わりに、ユースステートを使った処理を、独自のフックとして一つにまとめます。

7
00:00:32.363 --> 00:00:39.406
前回は状態を持たない通常の関数を部品化しましたが、今回は状態を持つ処理の再利用です。

8
00:00:39.406 --> 00:00:42.425
その違いも意識しながら進めましょう。

9
00:00:42.425 --> 00:00:49.132
完成形のイメージは、ボタン一つで説明欄が開いたり閉じたりする、小さな画面です。

10
00:00:49.132 --> 00:00:51.505
まず、カスタムフックの位置づけです。

11
00:00:51.505 --> 00:00:56.383
ユーストグルは、リアクトに用意された組み込みのエーピーアイではありません。

12
00:00:56.383 --> 00:00:58.360
自分で作る、独自のフックです。

13
00:00:58.360 --> 00:01:02.315
カスタムフックの名前は、ユースという言葉と大文字で始めます。

14
00:01:02.315 --> 00:01:07.325
この名前が目印になって、内部でフックを呼んでいる関数だと読み手に伝わります。

15
00:01:07.325 --> 00:01:09.566
呼び出す場所にも決まりがあります。

16
00:01:09.566 --> 00:01:13.389
コンポーネント、または別のフックのトップレベルで呼びます。

17
00:01:13.389 --> 00:01:18.003
条件分岐の中、繰り返しの中、クリック用の関数の中からは呼び出しません。

18
00:01:18.003 --> 00:01:21.167
呼び出しの順番が毎回同じになるよう保つためです。

19
00:01:21.167 --> 00:01:23.672
この決まりは、基本のフックと同じです。

20
00:01:23.672 --> 00:01:24.701
実装を見ます。

21
00:01:24.701 --> 00:01:31.608
ファイルは、エスアールシー配下のフックスフォルダーに、ユーストグル・ティーエスとして置きます。

22
00:01:31.608 --> 00:01:36.163
中ではユースステートで、イズオープンのという真偽値を持ちます。

23
00:01:36.163 --> 00:01:42.629
初期値は引数のイニシャルバリューで、省略するとフォルス、つまり閉じた状態から始まります。

24
00:01:42.629 --> 00:01:49.683
返すのは、現在の状態であるイズオープンのほかに、トグル、オープン、クローズという三つの関数です。

25
00:01:49.683 --> 00:01:53.210
呼び出し側は、この四つを受け取って使うだけです。

26
00:01:53.210 --> 00:01:57.178
開閉の細かい処理は、フックの中に閉じ込められています。

27
00:01:57.178 --> 00:02:00.852
わずか数行ですが、再利用の単位として十分な形です。

28
00:02:00.852 --> 00:02:03.323
三つの関数の違いを押さえます。

29
00:02:03.323 --> 00:02:08.923
トグルは、直前の状態を引数に取る更新関数を使い、真偽値を反転します。

30
00:02:08.923 --> 00:02:14.029
直前の値をもとにする書き方なので、一つの操作で更新が続けて予約されても、

31
00:02:14.029 --> 00:02:19.134
古い値だけを基準に反転してしまう事故を避けられます。

32
00:02:19.134 --> 00:02:26.217
一方、オープンは何度呼んでも開いた状態にし、クローズは何度呼んでも閉じた状態にします。

33
00:02:26.217 --> 00:02:33.629
今の状態が分からないときの反転と、結果が決まっている明示的な変更とで、使い分けてください。

34
00:02:33.629 --> 00:02:36.758
なお、引数の初期値は初回だけの値です。

35
00:02:36.758 --> 00:02:41.535
後から引数が変わっても、状態は自動ではリセットされません。

36
00:02:41.535 --> 00:02:46.146
常に親から制御したい場合は、親で状態を持つ設計にします。

37
00:02:46.146 --> 00:02:51.005
迷ったら、結果がどちらかに決まっている操作にはオープンとクローズ、単に切り替えたい操作にはトグル、

38
00:02:51.005 --> 00:02:55.864
と覚えてください。

39
00:02:55.864 --> 00:03:01.125
次に、アプリ・ティーエスエックスで、このフックを画面から使います。

40
00:03:01.125 --> 00:03:07.184
ユーストグルを呼び、分割代入でイズオープン、トグル、クローズを受け取ります。

41
00:03:07.184 --> 00:03:11.329
ボタンにはオンクリックとしてトグルを渡し、文言は状態に応じて、説明を開く、

42
00:03:11.329 --> 00:03:15.475
説明を閉じる、と切り替えます。

43
00:03:15.475 --> 00:03:20.736
説明のパネルは、イズオープンがフォルスのときにヒドゥンで隠れます。

44
00:03:20.736 --> 00:03:25.679
パネルの中にも閉じるボタンを置き、こちらはクローズを呼びます。

45
00:03:25.679 --> 00:03:31.578
コンポーネント側には、状態をどう反転させるかという細部は一切出てきません。

46
00:03:31.578 --> 00:03:35.564
受け取った値と関数を、表示と操作につなぐだけです。

47
00:03:35.564 --> 00:03:39.660
この例では、支援技術への配慮も状態と連動させています。

48
00:03:39.660 --> 00:03:46.639
パネルのアイディーは、第四回で学んだユースアイディーで作り、部品ごとに重ならない値にします。

49
00:03:46.639 --> 00:03:54.529
ボタンにはアリアコントロールズでそのアイディーを指定し、どのパネルを開閉するボタンなのかを結びつけます。

50
00:03:54.529 --> 00:03:59.156
さらに、アリアエクスパンデッドにはイズオープンをそのまま渡すので、開閉のたびに、

51
00:03:59.156 --> 00:04:03.783
展開されているかどうかが自動で追従します。

52
00:04:03.783 --> 00:04:12.583
見た目の表示だけでなく、こうした属性も同じ状態から決めることで、画面の見え方と読み上げの内容が食い違わなくなります。

53
00:04:12.583 --> 00:04:16.224
状態が一か所にある利点が、ここにも表れています。

54
00:04:16.224 --> 00:04:18.481
大切な性質を確認します。

55
00:04:18.481 --> 00:04:25.063
同じユーストグルを二つの場所で呼び出しても、状態はそれぞれ独立します。

56
00:04:25.063 --> 00:04:32.209
共通になるのは処理の手順、つまりロジックだけで、状態そのものではありません。

57
00:04:32.209 --> 00:04:38.979
たとえば説明欄を二つ並べ、片方だけを開いても、もう片方は閉じたままです。

58
00:04:38.979 --> 00:04:44.056
画面に書いた例のように、片方を引数なしで、もう片方をトゥルーの初期値で呼べば、

59
00:04:44.056 --> 00:04:49.134
開始状態も別々に決められます。

60
00:04:49.134 --> 00:04:56.656
フックを再利用すると状態まで共有されると思い込みがちですが、そうではありません。

61
00:04:56.656 --> 00:05:01.922
呼び出しごとに、ユースステートが新しく作られるからです。

62
00:05:01.922 --> 00:05:08.692
実際に二つ並べて試す確認方法は、最後の動作確認でもう一度取り上げます。

63
00:05:08.692 --> 00:05:14.293
では、複数の部品で同じ開閉状態を共有したいときは、どうするのでしょうか。

64
00:05:14.293 --> 00:05:21.294
答えは、共通の親でユーストグルを一回だけ呼び、その値と関数をプロップスで子へ渡すことです。

65
00:05:21.294 --> 00:05:28.139
これは、状態の置き場所を共通の親へ引き上げる、というこれまでの考え方とまったく同じです。

66
00:05:28.139 --> 00:05:36.074
フックはあくまで、状態と操作をまとめる道具であり、置き場所を決めるのはコンポーネントの構成のほうです。

67
00:05:36.074 --> 00:05:43.231
共有したい範囲が広がったら親へ、狭い範囲で閉じるならその部品の中へ、と役割で決めてください。

68
00:05:43.231 --> 00:05:47.120
コンテキストで渡す方法も、第二回で扱った通りです。

69
00:05:47.120 --> 00:05:50.151
補足として、関数の参照について触れます。

70
00:05:50.151 --> 00:05:55.304
この実装で返すトグルなどの関数は、レンダーのたびに新しく作られます。

71
00:05:55.304 --> 00:05:59.093
通常のボタンへ渡すだけなら、これで問題ありません。

72
00:05:59.093 --> 00:06:03.943
もし、関数の参照が変わらないことを前提にする仕組みへ渡すなど、安定性が必要な場面では、

73
00:06:03.943 --> 00:06:08.793
ユースコールバックで包むことを検討します。

74
00:06:08.793 --> 00:06:12.885
ただし、付ければ常に速くなるというものではありません。

75
00:06:12.885 --> 00:06:18.190
第五回で学んだメモ化と同じく、必要性が見えてから追加するのが原則です。

76
00:06:18.190 --> 00:06:24.252
まずはシンプルな実装を保ち、困る場面が来たら、その理由と一緒に見直してください。

77
00:06:24.252 --> 00:06:26.303
動作確認の手順を整理します。

78
00:06:26.303 --> 00:06:33.776
まず初期状態では閉じていること、ボタンを一回押すと開くこと、もう一回押すと閉じることを順に確かめます。

79
00:06:33.776 --> 00:06:39.637
次に、ユーストグルにトゥルーを渡した場合は、最初から開いていることを確認します。

80
00:06:39.637 --> 00:06:48.135
さらに、同じフックを使う説明欄を二つ用意し、片方だけを操作しても、もう片方の状態が変わらないことを確かめてください。

81
00:06:48.135 --> 00:06:53.117
今回、この開閉の遷移や初期値、独立性といった考え方をノード・ジェーエスで実行し、

82
00:06:53.117 --> 00:06:58.099
二十二件すべてが記事の期待と一致することを確認しました。

83
00:06:58.099 --> 00:07:01.029
型チェックでもエラーはありませんでした。

84
00:07:01.029 --> 00:07:06.304
ボタンの文言や属性が状態に追従しているかも、あわせて見るポイントです。

85
00:07:06.304 --> 00:07:07.242
まとめです。

86
00:07:07.242 --> 00:07:15.526
開閉のような、状態と操作の組になる処理は、カスタムフックにまとめると、どの画面でも同じ形で再利用できます。

87
00:07:15.526 --> 00:07:24.279
状態は呼び出しごとに独立し、共有したいときは親で一回呼んで渡す、という置き場所の判断もあわせて押さえてください。

88
00:07:24.279 --> 00:07:31.937
一方、ブラウザー上でボタンを押して表示の切り替えを目で確認する作業は、実行環境の制約で未実施です。

89
00:07:31.937 --> 00:07:38.346
気になる方は、手元のバイト環境で記事の二つのファイルを保存して試してみてください。

90
00:07:38.346 --> 00:07:44.285
次回は、エーピーアイのゲット処理を共通化する、フェッチジェイソンを学びます。

91
00:07:44.285 --> 00:07:45.692
お疲れさまでした。
