システム開発で思うところ

Javaで主にシステム開発をしながら思うところをツラツラを綴る。主に自分向けのメモ。EE関連の情報が少なく自分自身がそういう情報があったら良いなぁということで他の人の参考になれば幸い

Reactでの開発メモ

はじめに

vermeer.hatenablog.jp

を参考にしながら開発しながら思ったメモ
(※当面随時更新)

メモ

実装のベースとその理由

第13章のSuspenseにページルーティングはv6を使う。
まだ本リリースはしていない機能だけれど実装の印象だけで判断。
外部公開するものでもないので ライブラリが安定版であるかどうかじゃなくて直感的にわかりやすい書き方ができる方を優先しようと割り切り。
技術課題があったら、あったでその時考える。少なくとも書籍の範疇であれば「動くらしい」ということは保証されている割り切り。

本を読みながらとったメモ

  • useStateで状態と状態変更をする
  • useEffectで状態遷移(第2引数が監視対象の変数)を管理してステートパターン的に処理をする
  • useMemo を使って計算結果をコンポーネントシステムの外に保存しておく。依存配列が変わった時だけ再計算する。
  • useCallbackは関数のメモ化。関数を共有したいとき&依存配列が変わった時だけ再処理したいときに使う。
  • useRefは初期ロード時にリアルDOMへの参照を取得して処理する(初期フォーカスとか)&再レンダリングを伴わずに何らかのデータを関数コンポーネントで保存しておくときにも使える
  • useRef は useState と違って値の変更がコンポーネントの再レンダリングを発生させない
  • Custom Hook
    関数の名前の頭に『use』をつける
  • SPA におけるルーティングとは『DOM の動的な書き換えによってページ遷移を擬似的に実現するとともに、ブラウザのセッション履歴をそれに同期させること』
  • ほとんどの場面では Route は Switch といっしょに使う
  • <a> タグを使って書くと、そのリンクを踏んだ時点で React Router の管轄外となり管理していた履歴がすべて消える
    (Web サーバにリクエストが飛んで、SPA のコード全体がリロードされるため)
  • リンク先を設定する属性の to にはパスの文字列またはlocation オブジェクトを渡すことができる。
    location オブジェクトならパスの他にクエリパラメータやハッシュも設定できるし、ユーザーに見せたくない情報を埋め込んでリンク先に受け渡すこと ができる
  • boolean 型の属性である replace を指定すれば、クリックした時点でページの履歴が消える
  • useRouteMatch なら match オブジェクトをまるごと取得できる。マッチした URL パラメータにしか用がないときは useParams を使ったほうが便利
  • 『Atomic Design』という UI デザイン手法を適用
    Atoms、Molecules、Organisms、Templates、PagesのUI パーツを分ける
  • React Helmet
    ライブラリで、どこからでも HTML ドキュメントヘッダを動的に上書き
    SPA では意図して書き換えないと常に public/index.htmlに書かれた <title> の中身がどこのページでもそのページタイトルになるので注意
  • 任意のコンポーネントでいつでもルーティングできる(できてしまう)
  • useEffect を使ってコンポーネントの初回レンダリング時に強制的にトップにスクロールさせる(という実装例あり)
  • Modelじゃなくてコンポーネントを主軸にしてフロントエンドは実装するみたいなので設計や実装の考え方を変える必要あり
  • useReducerで状態変更の手段を複数持たせられる
    -- (状態管理の手段が単一の場合はuseState、複数の場合はuseReducerをつかう?)
  • useContextで状態を扱う
    --(Recoilもあるけどそちらは使わないことにする。Providerで親から渡してuseCallbankで振る舞いを実装)
  • 状態変更からリダイレクトでページ遷移するときは「Navigate」でパス指定する

ページ遷移

App.tsx にまとめて書く
Routerを作って、Appから呼び出すという実装にはしない RoutingはContainerの仕事(だからAppの仕事でもある)

LinkとNavigateはComponentで明示するとよい?(ページ遷移の副作用はViewで分かったほうが分かりやすい?)

パッケージ構成

  • ComponentとContainerの違いを意識する
  • ComponentとContainerについて - Qiita
  • Reactに関係するものだけをComponentとContainerに格納
    --(それ以外はdomainという感じでフォルダを分ける)
  • contextはファクトリーと型をペアにして作成する(Containerフォルダに入れる)
  • (複数ページ、複数機能でのパッケージ構成は1つ目を作ってから改めて考える)

ファイル構成

  • Container側の関数名に「Enhanced」などを付与して名前衝突を回避する
    (Componentだけで画面構築ができるケースもある=Container側がオプショナルになると考えから)

実装の順番(ToDoメモ的なもの)

初回の作成順序

一回作って全体の工程を把握しつつ実際に動くものを作る流れの整理

  • ベースのページ枠を作る(Component)
  • ページ遷移を試す(単純なリンク)
  • ページ内の動作や動的書き換え部分を作る(状態遷移で宣言的に)
    -- (ここまではデータ分離はしていない)
  • データ(固定)の埋め込み動的なモック状態へ
    -- (この時点ではコンポーネントを分割しないで割とベタに1つのファイルでゴリゴリ)
    --(ここまではコンポーネントの切り替えのContext以外は使用していない)
  • ページ内で使用するモデル(type)を作る
  • アプリの主要な機能を実装
    --(機能実現のための状態管理を含めて実装)
  • 共通機能であるタイマーコンポーネントを作成して埋め込む
    -- (ここまででデザインはともかくとして主要な機能は出来ている)
  • ファイル分割をする
  • CSS in JSを使ってデザイン(Component)を組み入れる
  • StoryBookを使ってコンポーネントのデザインを確認できるようにする
  • 状態によってCSSを変えたい部分の追加実装(状態遷移)
  • テストを実装
  • (E2Eは迷い中。まずはそれ以外かな。)

2つ目のアプリに向けて

  • monorepo構成に変更
  • アプリ共通部分と個別の部分を分ける
  • buildをして意図した資産出力がされるか確認する
  • script周りを整理(test)
  • パッケージの役割と実装パターンを整理
    -- (動くだけモノから、次の開発プロセス的やアーキテクト的な整理をちゃんとする)

2つ目アプリ

(ざっくり。1つ目を作った後で見直す) - ComponentとStoryBookで表記コンポーネントだけを実装 - モデル(type)を作成 - 検証用のデータを作成 - Containerを作成 - テストを実装

理解のイメージ

AppはルートとなるContainer。次にPageのComponent。
部品となるPanelのContainerへ問いかけて ViewとなるComponentを受け取って表示。
これを繰り返したミルフィーユでReactは画面を構築する。
僕にとってなじみの画面構築はテンプレートということが ようやくわかった気がする。テンプレートはViewのパーツを組み合わせて、そこからContainerに相当するアクションを呼び出す。
(思考が1つ前に進んだ気がする。)

実装の流れ

containerとComponentの往復をしながら作り込んでいく。
はじめは往復が面倒だったけど、フォルダであれファイルであれ デザインと実装の分離はStoryBookの利用も考えると分けておきたい。
いずれにしても何かしらの分離は必須だから多かれ少なかれ往復は発生するので心理的には許容範囲。
(当初は「理解のイメージ」がピタッときていなかったけれど、それがイメージできたら急に読みやすくなった。)

イベント処理

useKeyPress React Hook - useHooks

Reactでkeydownイベントを取得する方法

コンポーネント制御

構成と実装方針

コンポーネントの表示切り替えは同一区分の状態で管理するので、個別にファイルを分けずに1つのファイルで複数FCを集約したオブジェクトにする(イメージはインナークラスの呼び出し)。
useContextの使用を共通化は出来ないので、実装の共有ということは出来ないけれど、管理対象のグループ化にはなる。
フォルダで管理するという方法もあるけれど階層が深くなるだけのように感じたので「ファイル」で管理とした。
表示条件判断もContextが保持している状態文字列判定だけだから、そのためにわざわざメソッドも作らない。

参考情報

Reactのデザインパターン Compound Components - Qiita

Compound React Components with Hooks + TypeScript | Martin's Blog

[redux] Presentational / Container componentの分離 - react-redux.connect()のつかいかた - Qiita
(Reduxの話ではあるけれど「Provider直下のコンポーネントはPresentational componentであるのがよいらしい」らしい)

TECHSCORE|React: そのrender()はいつ呼ばれるのか | TECHSCORE BLOG

How to get previous props/state with React Hooks - LogRocket Blog

さいごに

現時点では未完