React + Reduxのプロジェクトでブラウザバックの時はscrollTopさせないようにする方法

React + Reduxのプロジェクトでブラウザバックの時はscrollTopさせないようにする方法

React + Reduxのプロジェクトの場合、基本的にページ遷移したらscrollTopさせるんですが、ブラウザバックの時などはscrollTopさせたくない場合があったりします。
その辺の実装が以外に簡単だったんでメモ。

Ads

前置き

React + Reduxのプロジェクトが前提なのでその辺はインストール済みってことで話を進めます。

あとはRoutingでreact-routerreact-router-reduxも使うのでその辺もインストールします。

$ npm install --save react-router-redux react-router 

Root.jsを修正

Routerで全部ラップしているContainerにscrollTopやブラウザバック時の処理を書きます。

Root.js

import {bindActionCreators} from 'redux'
import React, {Component, PropTypes} from 'react'
import {Provider} from 'react-redux'
import routes from '../Routes'
import {connect} from 'react-redux'
import {syncHistoryWithStore, routeActions} from 'react-router-redux'
import {Router, browserHistory} from 'react-router'

class Root extends Component {
  static propTypes = {
    store: PropTypes.object.isRequired
  }

  constructor(props) {
    super(props)
  }


  render() {
    const {store} = this.props

    const history = syncHistoryWithStore(browserHistory, store)
    history.listen(location => {
      setTimeout(() => {
        /** ブラウザバックならreturn **/
        if (location.action === 'POP') {
          return
        }
        /** それ以外はページトップへ移動 **/
        window.scrollTo(0, 0)
      })
    })

    return (
      <Provider store={store}>
        <Router history={browserHistory}>
          {routes}
        </Router>
      </Provider>
    )
  }
}

function mapStateToProps() {
  return {}
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(Object.assign({}, routeActions), dispatch)
}

export default connect(mapStateToProps, mapDispatchToProps)(Root)

この部分でやっています。location.actionがPOPの場合はブラウザバックなので、returnさせています。他にもPushとかもあるので色々処理を分けられそう。

const history = syncHistoryWithStore(browserHistory, store)
history.listen(location => {
  setTimeout(() => {
    /** ブラウザバックならreturn **/
    if (location.action === 'POP') {
      return
    }
    /** それ以外はページトップへ移動 **/
    window.scrollTo(0, 0)
  })
})

Reducerに追加

routerReducerをreducerに追加。

RootReducer.js

import {combineReducers} from "redux"
import {routerReducer} from 'react-router-redux'
import usersReducer from "./modules/Users"

export default combineReducers({
  user: usersReducer,
  routing: routerReducer
})

ちなみに、Reducerに追加しているのでpropsでroutingが使えます。各containerで色々できそうです。
試してないけどpathnameとかもあるから、naviとかで現在のページの場合はメニューがactiveとかに使えそうですね。

まとめ

インストールしたnpmパッケージはちゃんと仕様を理解すると作業が楽になりますね。数ヶ月前の自分は知らなくて結構四苦八苦したので教えてやりたいです。

オススメの本



ReactによるコンポーネントベースのWebフロントエンド開発の入門書。Reactでは小さくて管理が容易なコンポーネントを組み合わせて、大きくて強力なアプリケーションを作成できます。本書の前半は入門編で、簡単なサンプルを使いながらReactの基本やJSXについて学びます。後半は、実際のアプリケーション開発に必要なものや開発を助けてくれるツールについての解説です。具体的には、JavaScriptのパッケージングツール(Browserify)、ユニットテスト(Jest)、構文チェック(ESLint)、型チェック(Flow)、データフローの最適化(Flux)、イミュータブルなデータ(immutableライブラリ)などを取り上げます。対象読者は、ES2015(ES6)の基本をマスターしているフロントエンド開発者。

いいなと思ったらシェアお願いします

同じタグで検索

Ads

同じカテゴリーの記事

ページの先頭へ