中村的雑記

技術に関する記事を書いていきます。iOSエンジニア->Railsエンジニア。

react-routerとRailsのroutesを組み合わせる

はじめに

Reactでのフロントエンド開発を最近また業務でやっている。
前回やった時は半年ほど前に2,3スプリント分の機能を実装しただけなので、正直忘れてしまった状態からのスタートだ。
今回はreact-routerとRailsのroutesの兼ね合いについてのメモとしてこの記事を書く。
例の如くサンプルコード内の命名は無配慮なものになっているので、その点お目溢しを願う。

環境

React / TypeScript / Rails

背景

ユーザ登録の際に、一つ目のページでemailを入力し、二つ目のページでpasswordを入力する機能を作りたい。

(この記事では各種ページコンポーネントの実装は割愛する。 気が向いたら追記するかも。)

そして 1ページ目は

'/users/new/'

2ページ目は

'/users/new/pass'

というようなroutingを実現したい。

実装(React側)

Root.tsxは下記のような実装をした。

import React, { memo } from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { EmailPage } from "./EmailPage";
import { PasswordPage } from "./PasswordPage";
import styles from "./Root.modules.scss"
import { RegistrationContainer } from "./useRegistration";

export default function Root() {
  return (
    <BrowserRouter>
      <RegistrationContainer.provider>
        <Component />
      </RegistrationContainer.provider>
    </BrowserRouter>
  );
}

const Component = memo(function Component() {
  const { ROUTES } = RegistrationContainer.useContainer();
  return (
    <div className={styles.base}>
      <Switch>
        <Route path={ROUTES.pass}>
          <PasswordPage />
        </Route>
        <Route>
          <EmailPage />
        </Route>
      </Switch>
    </div>
  );
}

今回使うpass自体はRegistrationContainerの方でROUTESとして下記のように実装している。 (ちなみにこのcontainerはunstated-nextで生成している。)

const ROUTES = {
  password_pass: path.resolve(baseUrl, "./"),
  phone_number_pass: path.resolve(baseUrl, "./"),
} as const

Root.tsx内で上記containerから呼び出したROUTESのpassをRoute pathに代入している。

実装(Rails側)

今回登場したパス、

1ページ目は

'/users/new/'

2ページ目は

'/users/new/pass'

であるが、2ページ目のパスに関してはRails側は感知できないので、 ユーザーが2ページ目を開いている時にページを再読み込すると、Rails側が理解できないリクエストが送られてしまう。

なので、Rails側のroutes.rbで

get '/users/new/pass', to: redirect('/users/new')

とredirectしてあげれば良い。

最後に

どなたかのためになれば甚だ幸いだ。 また間違いなどあれば、ご指摘いただけると嬉しい。