JavaScript
webpack
React
react-router

react-router でネストされたURLを直打ちして 404 Not Found になる対処法

現象

以下のような Route 設定で

<Switch>
  ...
  <Route path="/login" render={() => <Login onClick={login} />} />
  <Route
    path="/subjects/:id"
    render={props => (
      <Subject
        items={this.state.items}
        subject={this.state.subject}
        getItemsCallback={subject_id => getItems(this, subject_id)}
        getSubjectCallback={subject_id => getSubject(this, subject_id)}
        {...props}
      />
    )}
  />
</Switch>

/login にはアクセスできるが、/subjects/:id にアクセスしようとすると、まっ白の画面に成り
console に以下がでる。

GET http://localhost:4000/subjects/bundle.js 404 (Not Found)

subjects/:id:id の部分が原因かと思い、試しに /login/login/hoge として試してみると、/login/hoge の方もアクセスできないことが判明する。
つまり、ネストされた URL に対応できていないことがわかる。

解決

エラー文を見てみると、http://localhost:4000/subjects/ の下に bundle.js があるかどうかをチェックしてしまっている。
bundle.js は http://localhost:4000/ を見てほしいので、そこをなんとかする。

webpack の設定を見ると、

webpack.config.js
module.exports = {
  entry: __dirname + "/src/index.jsx", // トランスパイル対象
  output: {
    path: __dirname + "/dist", // 出力先ディレクトリ
    filename: "bundle.js" // 入力されたファイルをまとめて出力するときのファイル名
  },
  ...

となっているので、__dirname + "/dist/bundle.js" をチェックして修正する。

before
dist/index.html
<!DOCTYPE html>
<html>
  ...
  <body>
    ...
    <script src="bundle.js"></script>
  </body>
</html>
after
dist/index.html
<!DOCTYPE html>
<html>
  ...
  <body>
    ...
    <script src="/bundle.js"></script> # 絶対パスにした
  </body>
</html>

参考

https://github.com/webpack/webpack-dev-server/issues/978