react reduxでReact Router V6を導入する

こんにちは、AG-Boost開発部の大塚です
react routerのversionを5 -> 6に上げた時のことを簡単にまとめます。

react routerとは

ReactのSPAでページ遷移を可能にするライブラリです。
urlに応じてcomponentを出し分けることで、あたかも複数のページが存在しているように見せることができます。

昨年末に最新のv6がリリースされました。
破壊的変更が多く、versionを上げる際は少し大変です。
公式documentにもアップデートの手引きが乗っています
Upgrading from v5

Routing設定

<Provider store={store}>
  <BrowserRouter history={history}>
    <Routes>
      <Route path="/login" element={<Login />} />
      <Route path="/user" element={<User />} />
      <Route path="/home" element={<Home />} />
        ・
        ・
      <Route path="*" element={<Navigate from="/" to="/home" />} />
    </Routes>
  </BrowserRouter>
</Provider>

reduxの場合、<Provider />という専用のタグでRouterをラップする必要があります。これによりreact-routerがreduxの管理するstoreにアクセスが可能になります。 その他は通常のrouting設定と同じです。

この辺はv5 -> v6で細かい仕様変更が入っているので注意が必要です。

フックの紹介

useNavigate

useHistoryに代わってv6で追加されたhookです。
指定のpathへ遷移ができます。replace, stateを指定することで、遷移方法を決めたり遷移先に値を渡すことができます。

import { useNavigate } from "react-router-dom";
const navigate = useNavigate();

navigate("/path", { state: "hoge"}, { replace: true });
navigate(-1); // ブラウザバックと同じ


(v5) -> (v6)
history.push('/home') -> navigate('/home')
history.replace('/home') -> navigate('/home', {replace: true});

useNavigationType

こちらもv6で追加されました。
現在のページに訪れた際のactionを取得できます。

import { useNavigationType } from 'react-router-dom';
const navigationType = useNavigationType() // POP or PUSH or REPLACE

(v5) -> (v6)
history.action -> navigationType

useLocation

import { useLocation } from 'react-router-dom';
const location = useLocation();

console.log(location)
// {hash: "", key: "default", pathname: "/home", search: "", state: null}

location.pathnameで現在のpathを取得できます。
navigate("/home", {state: 'hoge' })のように、遷移の際に渡した値はlocation.stateで確認できます。

useParams

<Route path="user/:id" element={<User />} />

navigate("/user/10");
import { useParams } from 'react-router-dom';
const { id } = useParams();

console.log(id) // 10

詳しくはこちらのdocumentに記載されています。

注意点

webpackの設定

devServer: {
  historyApiFallback: true
}

routingが上手くいかない場合、webpackの設定ミスの可能性があります。多分Cannot get 云々...とか出ます。 存在しないパスをリクエストされた場合に、404ではなく一度インデックファイルを返し、その中でルーティングを行います。 論理パスによりSPAを実現する場合はこの設定が必要です。

connected-react-routerは非対応

redux用のrouterでconnected-react-routerというライブラリがあります。Action内で簡単に画面遷移を実現できて便利ですが、v6には非対応なのでupdateの際は注意が必要です。。。

import { push } from 'connected-react-router';

export const login = (data) => (dispatch) => {
  .
  .
  dispatch(push("/home"));
}

最後に

今回のversionアップデートでは、変更箇所が多く修正に少し手間取りました。 特にルーティングの設定は細かい変更が多いので、アップデート後の挙動は要チェックです。v6導入の際にこちらの記事が少しでも参考になれば嬉しいです。