読者です 読者をやめる 読者になる 読者になる

オフトゥン大好き

惰眠系プログラマの作業ログで( ˘ω˘ ) スヤァ…

react_on_railsでreduxを使う

前回の続きでreduxを導入しました。

必要なnpmを追加

redux-thunkは非同期アクションを実現するパッケージなのであまり関係ありませんが、後々入れることになると思うのでついでに入れておきます。

yarn add redux react-redux react-router-redux redux-thunk

コードにstoreを追加する

サーバサイドのルーター

ブラウザのルーター

コントローラにもstoreを追加する

  # application_controller.rb
  def render_for_react(props: {}, status: 200)
    if request.format.json?
      response.headers["Cache-Control"] = "no-cache, no-store"
      response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
      response.headers["Pragma"] = "no-cache"
      render(
        json: common_props.merge(props),
        status: status,
      )
    else
      redux_store(
        "store",
        props: common_props.merge(props).as_json,
      )

      render(
        html: view_context.react_component(
          "Router",
          prerender: true,
        ),
        layout: true,
        status: status,
      )
    end
  end

テンプレートに<%= redux_store_hydration_data %>を追加。

reducerを追加

propsとrailsContextをinitialStateにぶち込み、react-router-reduxの提供しているルーティングに関するreducerと後で作るその他のreducersを全部放り込んでcombineReducersでまとめます。

  const initialState = {
    ...props,
    railsContext,
  };

  const reducer = combineReducers({
    ...reducers,
    routing: routerReducer,
  });

この時点でrailsContextReducerがないとエラーが発生するので、こいつを作っていきます。とはいっても最初のロード以外でこいつが処理を行うことは基本的にありませんのでstateをそのまま返すだけのものです。

export default function railsContextReducer(state = {}) {
  return state;
}

propsを出力すると以下のようにroutingrailsContextが含まれていることがわかります(reduxのconnectstateをそのままpropsマッピングした場合の出力)。

https://gyazo.com/b3f404fd17c025ff780762a3c04a0e97

関連記事

nukosuke.hatenablog.jp