reatc-router を使用している状況で、クエリストリングのパラメータ値が違う、同一ページに遷移する状況があったのですが、ページがリソースが更新されませんでした。
リソース更新のために実施したことを記載します。
前提
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 />
の記載位置がダメだったようです。
-
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
以上です。
-
taion/react-router-scroll: React Router scroll management というのもありましたが、react-router v4 だと使えなさそうでした。 ↩
コメント