Reactのroute改善のまとめ

Avatar photo
エンジニア 周瑜
2019年03月18日


mmjに入社してから、Reactでフロントエンドのコーディングをしています。
最初は各ページに一つのrouteをつけて管理していましたが、そうすると、関連ページのstatusが共有できなくて、全部propsで管理するか、全局変数で共有することをせざるを得なかったことがあります。全部をprops使って各ページの間に渡すと、検索条件等でもpropsに指定しなくてはなりません。propsが膨大になって、可読性が落ち、管理がしづらくなっていました。
そこで弊社のtk先生の指導の下で(ほとんどはtk先生が書いてくれました)、routeの構造を改造しました。

この改造で、同じDomainを1つのrouteにまとめました。
routeは2つの部分から構成されます。各ページのrenderer、と1つの親routeです。

各renderer

各ページに必要なstatusを定義と、そのstatusに対する操作のハンドリングの定義を保存する場所ですので、
各自のstatusを定義しますが、状態は持っていないです。
handleなどのメソッドを定義していますが、状態を引数として渡して、処理した後に返します。

ページを描画するreandererを定義します。rendererに必要な値とメソッドはrendererの引数として渡します。


function renderer(
  s: Status,
  xi: XXXInfo,
  setState:(s: Status) => void,
  setViewState: (s: View.Status) => void,
  setConfirmStatus: (s: Confirm.Status) => void
): React.ReactNode

従って、このページは状態をもたないです。

親route

routeなので、statusは持っています。
enumのmodeを定義して、各rendererをimportして使います。

  import * as View from './xxxRouteView'

Mode,Status,Propsを定義します。


enum Mode {
  Loading,
  View,
  Edit,
  Confirm
}

interface Status {
  mode: Mode
  modeStatus: Loading.Status | View.Status | Edit.Status | Confirm.Status
}

interface Props {
  xxxInfo: XxxInfo
}

本当のrendererはこのファイルに定義します。

class XxxRenderer extends Renderer

rendererの中に各ページのsetStateを対応します。


  setViewState = (s: View.Status) => {
    this.setState({ mode: Mode.View, modeStatus: s })
  };

modeによって、各ページを描画します。各rendererに定義したrendererはここで使います。


render(): React.ReactNode {
  switch (this.state.mode) {
   case Mode.Loading: return Loading.renderer(this.state.modeStatus as Loading.Status)
   case Mode.View:
    return View.renderer(
     this.state.modeStatus as View.Status,
     this.props.xxxInfo,
     this.setViewState,
     this.setEditState,
     this.backToTop
    )
   case Mode.Edit:
    return Edit.renderer(
     this.state.modeStatus as Edit.Status,
     this.props.xxxInfo,
     this.setEditState,
     this.setViewState,
     this.setConfirmState
    )
   case Mode.Confirm:
    return Confirm.renderer(
     this.state.modeStatus as Confirm.Status,
     this.props.xxxInfo,
     this.setConfirmState,
     this.setViewState,
     this.setEditState
    )
  }
}

以上が改善したrouteの構造でした。

最後にこの構造まとめ

  • ・一つのDomainに一つのrouteで管理することで、各ページの共通の状態を持つ事ができます。
  • ・各ページの状態をごちゃごちゃにしないように、ファイルに分けて管理します。
  • ・各ページのファイルにはstatusを定義していますが、状態は持ちません。状態を持つのは親のrouteだけです。
  • ・各ページにメソッドを定義していますが、状態を持っていないので、破壊的な修正がない限りは戻り値以外の副作用はないはずです。
  • 2019年03月18日

    エンジニア 周瑜 |

    « »
    このページのトップへ