reatc-router を使用している状況で、クエリストリングのパラメータ値が違う、同一ページに遷移する状況があったのですが、ページがリソースが更新されませんでした。
リソース更新のために実施したことを記載します。

[TOC]


前提

react、react-router の version は以下の通りです。

react@16.2.0
react-router-dom@4.2.2


同一ページのリソース更新方法

  • ルーテイング
    ルーテイングは、以下の通りです。
    "/posts/:slug"該当するページから、同じく該当するページへ遷移する際、リソースの更新が行えるようにしたいです。

    <Switch>
        <Route exact path="/" component={PostList}/>
        <Route exact path="/posts" component={PostList}/>
        <Route exact path="/posts/:slug" component={PostDetail}/>
        <Route exact path="/about" component={About}/>
        <Route component={NoMatch}/>
    </Switch>
    

  • 当初の実装
    componentWillMount で、リソースの取得を行なっていましたが、同一ページ遷移時は、既に Component はマウント済になるのか、componentWillMount呼び出されず、リソースの取得が行われなかったです。

        componentWillMount() {
            this.props.fetchPost(this.props.match.params.slug);
        }
    

  • 同一ページ更新時に、リソースの取得を行う
    componentWillReceiveProps追加し、ページのlocatioin 変化時に、リソースの再取得を行うようにしました。

        componentWillMount() {
            this.props.fetchPost(this.props.match.params.slug);
        }    
        componentWillReceiveProps(nextProps) {
            if (nextProps.location !== this.props.location) {
                this.props.fetchPost(nextProps.match.params.slug);     
            }
        }
    
    試していないですが、componentDidUpdate実装しても同様のことは実施できそうです。


スクロール位置の移動

componentWillReceivePropsリソースの取得を行うのみだと、スクロール位置が移動しませんでした。
この際に、ページTOPにスクロール位置を移動するようにしたいです。
react-router にreact-router/scroll-restoration.md at master · ReactTraining/react-router
いうドキュメントがあり、このやり方で実現できそうですが、ipatate/react-router-scroll-memory: React component to keep the scroll of the page and to restore it if the user clicks on the back button of its browserいうライブラリがあったので、ライブラリを使ってみます。1

インストール

npm i -S react-router-scroll-memory

実装 (エラーになった)

Doument を参考に以下のように実装しましたが、Uncaught Error: A <router > may have only one child elementいうエラーが発生しました。
<scrollmemory ></scrollmemory>記載位置がダメだったようです。

  • import文の追加

    import ScrollMemory from 'react-router-scroll-memory';
    

  • Router の下に ScrollMemory追加

    // --------------------------------------------
    // ReactDOM.render
    // ------------
    ReactDOM.render(
        <Provider store={store}>
            <BrowserRouter>
                <ScrollMemory />
                <Route path="/" component={Main}/>
            </BrowserRouter>
        </Provider>
        , document.getElementById("root"));
    

実装 (うまくいった)

以下のように記載を変更したところ上手く動作しました。

  • 直上に、ScrollMemory追加
        <div className="body">
            <Navbar toggle={this.drawerToggle}/>
            <ScrollMemory />
            <Switch>
                <Route exact path="/" component={PostList}/>
                <Route exact path="/posts" component={PostList}/>
                <Route exact path="/posts/:slug" component={PostDetail}/>
                <Route exact path="/about" component={About}/>
                <Route component={NoMatch}/>
            </Switch>
        </div>
    

参考

以下、参考にした、記事へのリンクです。

javascript - Reload a route that has state based on query params using React Router - Stack Overflow

【react-router】複数のパスで同一コンポーネント内を表示しつつ、それぞれの初期fetchを実行する方法 - Qiita

react-router v4で画面遷移時にトップから表示する方法 - Qiita

React.jsのComponent Lifecycle - Qiita

以上です。


  1. taion/react-router-scroll: React Router scroll managementいうのもありましたが、react-router v4 だと使えなさそうでした。 

コメント