Skip to content

Instantly share code, notes, and snippets.

@mizchi
Last active April 18, 2022 11:39
Show Gist options
  • Save mizchi/5e913612aeb803958ba78c757f75d857 to your computer and use it in GitHub Desktop.
Save mizchi/5e913612aeb803958ba78c757f75d857 to your computer and use it in GitHub Desktop.

react-redux の設計指針

はじめに

これは某所での設計を決める用の資料です

チェックリスト

  • フレームワーク
    • React
    • React/Redux (Recommended)
  • Redux Middleware
    • None
    • redux-thunk
    • redux-promise (Recommended)
    • redux-saga
    • redux-observable
  • Redux Reducer
    • Domain with Selector
    • Domainless
  • HMR
    • On
    • Off
  • SSR
    • On
    • Off
  • CSS
    • Independent
    • CSS Module
    • CSS in JS
    • styled-components
  • Type System
    • Babel/Flow
    • TypeScript

Redux について

vs Vue.js

  • 個人的な感想だと…
    • React/Angularに対して後出しジャンケンしてるので便利な部分は便利
    • React と同じ水準まで便利になることはあっても、Reactを超えることはないと思う

vs Angular

  • 個人的な感想だと…
    • 独自テンプレート、独自エコシステム、Rx界を許容するか
    • 僕はあんまり好きじゃないです

Redux

Redux の基礎概念

コアはこれだけ

type reducer = (State, Action) => State
  • 前の状態と、新しく流れてくる Action で、次の状態を決める
  • 複数の reducer を合成して一つの関数にする(ことが多い)

Redux の Reducer

Redux の reducer の派閥

  • ビューに関与するデータだけ持つ派
    • ドメイン層を直接知らない
    • Presentational な Layer に徹する
  • ドメインデータを大量に持つ派
    • ドメイン層に近い振る舞いをする
    • ビューに関与するデータ

reducer: ビューに関与するデータだけ持つ派

  • 画面ごとにその画面を抽象する reducer を置く
  • RESTに応じてその結果をそのまま格納してそのまま表示する
  • サーバー側のデータ構造と密に紐づく

redecer: ドメインデータを大量に持つ派

  • Twitter Mobile だと…
    • tweets[id] = {...} という Map 構造に格納する
    • timeline = id[]mentions = id[] という配列でリレーショナルな構造をとる

画面に表示する際は、ステートからさらに再計算してReactに渡す。 それらを selector と言ったりする。 そのヘルパが https://github.com/reactjs/reselect

reducer の設計はどっちが良いか

  • 要件/複雑度次第
  • どっちが正しいとかはない
    • 現実的な「Web」だと前者がフィットするし、デスクトップアプリだと後者に近づく

Redux Middleware

Redux Middleware の考え方

  • Actionのストリームを別のストリームに変換する層
  • 名前がよくない。 Action Mapper とかが適切では

Middleware の派閥

  • Middleware 不要派
    • 必ず直接 reducer へ dispatch する
    • ビューにロジック書かれがちなのが難点
  • 用途ごとに middleware 書く派
    • たとえば 特定のエンドポイントの api call を抽象する
    • 無限に増えていくので実質↓と変わらない状態になりがち
  • thunk派
    • middleware api がむき出しで自由度が高すぎる
    • redux の中の実装に踏み入りすぎてしまう
  • promise派
    • 素朴
    • 1:1 の関係以外うまくかけない
  • saga派
    • ジェネレーターで状態を抱えながら複数回 dispatch
    • アクションとreducerへのdispatchの 1:N や N:1 の関係をうまく書ける
    • 状態を抱える奇形なRxだと思う
  • Rx派 (redux-observable)    - Angular と違って React界では主流ではない

Actionと dispatch の M:N とは何か

  1. ビュー側から request-api-call を dispatch
  2. middleware が lock-ui を発行
  3. middleware が update-api-result を発行
  4. middleware が unlock-ui を発行

これで 1:3 の関係

GraphQL は必要か?

  • 不特定多数に公開するAPIのデータのペイロード削減に効果を発揮
    • 逆に言えばそうでないケースはオーバーキル
  • 真に必要なのは「複数のリクエストを合成する層」で、要は愚直なRESTのN+1問題を避けたい
    • GraphQL持ち出さずとも、サービスごとに View API を提供すれば解決する問題
    • 教条的なRESTに縛られると重大なパフォーマンス問題を抱えることが多い
  • 結果としてBFFと切り口は同じ

SSR は必要か?

  • SEO を気にするなら残念ながら現状必須 (Google頑張って…)
  • First Meaningful Paint を気にするならやる
  • 「いずれやりたいね」程度でも最初からそういう設計にしないと後付は難しい
  • そうでないなら余力がよっぽどない限りはやらない
  • BFFを置けるなら next.js などで対応可能

React のテストは必要か?

  • なかなかペイしづらい部分
  • 後方互換の確認にスナップショットテストが有用
  • やるならava/enzyme を推奨

Reducer のテストは必要か?

  • 純粋関数なので書きやすい、が…
  • Reduxがドメインレスな場合、あんまり意味がない(サーバー側に実体があるため)

E2E テストは必要か?

  • pupetteer が便利そう
    • ヘッドレスChromeなのでクロスブラウザテストは別途必要
  • PRごとに連番スクショで目視チェックぐらいがペイする限界ではないか

HMR は必要か?

  • 何かと壊れるので維持が大変
  • マークアッパーと JSer で前者の人数が多いならメリットが大きい
  • 素早くコンポーネントをプレビューしたい、程度なら react-storybook などで十分な可能性がある

CSS Module は必要か?

  • 何かと壊れるのでry
  • webpack での設定がヤバイ感じになるので、メンテ側としてはあまり入れたくないが…
  • こだわりがないなら要件をマークアップする人の意見で決めるのがよい
  • semantic-ui-react などで基本的なデザインを丸投げするという方法もなくはない

ReactRouter は必要か?

型システムは必要か?

  • 現代ではとりあえず必須でいいのでは
  • Flowの方が導入は楽だし負荷は少ない
  • TypeScriptは開発環境を揃えたり周辺ライブラリの型を整えれば強い

Yarn or NPM5 ?

  • 個人的には yarn
  • npm5 が遅くて色々壊れててストレス
  • monorepo も構成もアリ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment