react-routerが都合よくAPIを公開してくれた!(がダメだった)

mk.hatenablog.com

かなり前ですけど、react-routerのURLをreduxで管理していい感じ、というコード書きました。こちらはreact-routerの非公開関数を利用していたので将来危険だなあと思ってましたが、4.xでやっぱりダメになりました。しかしそれは良い方向の変更で、利用していた非公開関数の同等機能をきちんとAPIにしてくれてたのです。イシューまでは読んでませんが、私のようなことをしてた人の要望だったのかも。

react-router/matchPath.md at master · ReactTraining/react-router · GitHub

利用するのは上記リンク先ドキュメントのmatchPathというAPIです。ちなみにリンク先ドキュメントは今日時点でほとんど何も書かれていないので、直に実装コードを読まないと使い方わかりません。

該当箇所は以下のとおりに元記事のReducer内のヘルパ関数の中身を書き直します。申し訳ないのは元記事ではtitleをURI内パラメータ、pageをクエリー値でもってくる仕様だったのを、title、vol、pageを全部URIエンコードされている仕様に変更してたわ。

import { matchPath } from 'react-router';

function decodeTitleAndPage(pathname) {
    const m = matchPath(pathname, { path: '/:title/:vol/:page' });
    if (!m) {
        return {};
    }
    let title = '';
    let vol = '';
    let page = 0;
    m.params.forEach((value, key) => {
        if (key === 'title') {
            title = value;
        } else if (key === 'vol') {
            vol = value;
        } else if (key === 'page') {
            page = Number(value);
        }
    });
    return { title, vol, page };
}

ダメだった

おっとどっこい。react-router-reduxがreact-routerの最新バージョンに追いついていない!動いていたみたいなのはブラウザのキャッシュが効いてただけでした。テストを走らせたら爆発して気づき、キャッシュクリアしたらちゃんとアプリも壊れました。そっと上の修正をもどして、react-routerも3.0.5にもどしました。

なにやらreact-router-reduxがreact-routerにマージされていくような様子?5.xでちゃんとするようなことが書いてあった。きちんとバージョン上がったときへの備忘録として記事は残しておきます。

4.xでなんで動かないか

ちょっと見てみた。

export const LOCATION_CHANGE = '@@router/LOCATION_CHANGE'

export function routerReducer(state = initialState, { type, payload } = {}) {
  if (type === LOCATION_CHANGE) {
    return { ...state, location: payload }
  }

  return state
}

react-router-reduxのrouterReducerのAction仕様が変わってる。反応するtypeの文字列が ‘@@router/LOCATION_CHANGE’ になってるし、パラメータ名が ‘location’ になってる。3.xではそれぞれ ‘locationChange’ と ‘locationBeforeTransitions’ 。まずこれだけで動くわけがない。