旧gaaamiiのブログ

間違ったことを書いている時があります。コメントやTwitter、ブコメなどでご指摘ください

React Routerを使って、イベントが起きたときにURLを変えつつ何か処理をする

SPAを作っていると、何かイベントが起きたときにURL変えつつなにか処理をしたいということがあります。 たとえば絞り込み検索で、クエリストリングだけ書き換えて画面更新したいというケース。具体的には/blog_posts から /blog_posts?tag=1 へ遷移するような感じです。history.listenにコールバックを渡すと、これが実現できたのでメモしておきます。

まずは実装例

interface Props extends RouteComponentProps {
  hoge: string;
}

class MyPage extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props)
  }

  componentDidMount() {
    this.unregisterHistoryCallback = this.props.history.listen((location: LocationDescriptor) => {
      this.updateMyPageData(location.search.toString())
    })
  }
  
  componentWillUnmount {
    this.unregisterHistoryCallback()
  }
  
  private updateMyPageData(query: string) {
    // ...
  }

  private pushHistory(obj: any) {
    const query = QueryHelper.toQueryString(obj)
    this.props.history.push({ search: query })
  }
}

やっていること

URLつくる -> URLに紐付いた状態更新メソッド的なもの(updateMyPageData)を呼び出している。

やっていること詳しく

ポイントは、URLが変わったときに呼ぶコールバックの登録と解除。それを history.listen というメソッドで行っている。listenは、コールバックを登録してそれを解除する関数を返すので、登録時の返り値を保持しておいて、コンポーネントのunmountのタイミングでそれを呼べば良い。

追記

上記のやり方では props.match.params (たとえばURLが /users/{userId}/posts?hoge=fugauserIdの部分)を、最新のものを参照できなくて悩んでたのですが、以下の記事を読んで、React Routerのlocationを使えばいいことを知りました。

qiita.com

参考