Closed4

React の設計について

おしぼりおしぼり

以下の点が知りたい。

  • CSS スタイリングの技術選定方法
  • state に関わるハマりどころ
  • state の数を爆発させないための Tips
  • props に関わるハマりどころ
  • flex スタイルのレイアウト設計の基本
  • 変更に強いコンポーネントの設計方法
  • カスタム hooks の使い所
  • レンダリングに関して最低限注意すること
  • フロントエンド側でやること・やらないこと (React に限らない)
  • 認証・認可に関わるフロントエンド側の実装の技術選定・取捨選択
  • 状態管理ライブラリの技術選定方法
おしぼりおしぼり

Props に関して

true を渡す場合は単に porps 名を指定するだけでもよい

設定やフラグのようなものを on にする場合はこの指定方法がよさそう

オブジェクトは spread や rest spread で渡せる

spread
const huga = {name: "name", email: "email"}; 
<Hoge {...huga} /> 
rest-spread
const huga = {name: "name", email: "email", pass: "pass}; 
const {name, ...rest} = huga; 
<Hoge {...rest} /> 

Object Destructuring

function Hoge({name, email}) { ... } 

props の値を state の初期値に使う

良いのか悪いのかわからないけど、たまにやりたくなる。理屈としては「定数として表現はできない(= 事前に定数としてコンポーネント内に定義することは難しい)が、コンポーネントの初期化前には入れるべき値がわかり、かつそれを親から渡したい & 一度渡したら変更したくない」場合に使う気がする。form などの初期値を親から props で渡したい場合には使えるのかも(参考)。まあよくわからん。

おしぼりおしぼり

コンポーネントの設計

オブジェクトを利用した conditional なコンポーネント

こちらより引用。微妙な気もする。状態が 2 パターンしかないなら三項演算子を使う。

const {role} = user
const components = {
    ADMIN: AdminUser,
    EMPLOYEE: EmployeeUser,
    USER: NormalUser
};

const Component = components[role];
return <Componenent />;

div の代わりにフラグメント

こちらより引用 。なるほど。

state アップパターンによる再レンダリングの防止

再レンダリングさせたくないコンポーネントをそのまま(= あるコンポーネントの子コンポーネントとして)定義するのではなく、props としてあるコンポーネントに渡してやる。

memo による再レンダリングの防止

そもそも props の値が変化してないのに再レンダリングしたいケースなんてあまり無いのだから、全てのコンポーネントで memo 使ってはいけないの?と思うけど、どうなんだろう。

カスタム Hook あるいは Contaienr / Presentation パターン

ここ を読む。個人的には記述量も大事だと思うのでカスタム Hook で良いかなあと思う。Hook の用途が増える / 一部変わるとコンポーネントと Hook の両方に変更が必要という点が欠点みたいだけど、単純に関心を分離する目的と割り切って共通化のためにやるわけじゃないならあんまり気にすることもない気がする。まあ変更することになったら普通に頑張って Hook を変更するで良い気がする。

function か const か

ここ を読んだ感想としてはどっちでも良いかなあ。

Reducer

state (とそれに伴うイベントハンドラ・イベントハンドラ内で使うロジック関数)が増えてつらいに対する一つの処方箋として使える。Redux と思想は同じ。コンポーネントの責務が UI の表示とイベントの dispatch に限定されるので見通しが良くなる。複数の state を同時に変更するような場合にも良い。基本的に useState は非同期なので、守りたい順序関係があるなら useReducer を検討しても良いかも。ただ、コンポーネントが持つ状態がシンプルかつ順序関係などを持たないなら使わなくても良い。Redux がいけてなかったのは全部を Redux の仕組みの中でやるからで、コンポーネントごとに複雑度が違うので適切に useState と useReducer を使い分けていく感じが一番シンプルで良いのではないか。

Context

状態を複数のコンポーネントで共有したくなったら使うくらい

複数の state をカスタム Hook で隠蔽する

state 数の増加問題への対処法の一つ。ただ、データフェッチとかは SWR みたいなよくできたライブラリを使う方が良いかも。

メモ

  • state の数を増やすと「子コンポーネントが無駄にレンダリングされる状況を作りやすくなる」&「 状態管理が煩雑になる」ので適切にコンポーネントを切った方が良い。なんか普通の関数定義だと使い回すかどうかの共通化の文脈で切り出すことが多いけど、state を閉じ込めるためにそこでしか使われないコンポーネントでも切り出すメリットがあることを把握できたのはよかった。
  • 切り出せる state は「自身の state の変更を親コンポーネントに伝搬する必要があるか」で見極める
  • 完全に JS とは関係ないけど、Email のバリデーション処理を書く時に Email というクラスにその機能を持たせるか Validator みたいな汎用クラスを定義するかで悩むことがある
おしぼりおしぼり

CSS スタイリング方法について

結論としては Tailwind CSS を使うことになりそう。かなり雑な選定理由ではあるが ... 。

CSS Modules

やっぱり .css ファイルを毎回作るのは辛い。

Styled Component

個人的にはレイアウトとスタイル( HTML が持つ役割と CSS が持つ役割)は明確に分けたい。スタイルを持った HTML タグを生成してやるよ、みたいな思想は合わなかった。

Emotion

ありだけど、もっと簡単に書けたら嬉しい

Tailwind CSS

短くかける。これに尽きる。

結局 MUI とかまでガッツリライブラリを使いたくないけどよくあるスタイルなら定義済みパーツが使えて、自分でもそれなりにカスタムできる、みたいなのが欲しかったのでちょうど良い。

このスクラップは2023/11/18にクローズされました