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=fuga
のuserId
の部分)を、最新のものを参照できなくて悩んでたのですが、以下の記事を読んで、React Routerのlocationを使えばいいことを知りました。