react-routerをreduxで使うためのreact-router-reduxというものがあります。
先日、これの型定義ファイルが公開されてたので使ってみました。
react-router-reduxの公式サイトはこちらになります。
素のreactのプロジェクトに対して…
- react-redux
- react-router
- react-router-redux
- redux
- history
あたりを追加してやれば使える感じになります(多いよね…)
reducerの設定
react-router-reduxを使うには、routingというものをreducerに含めておく必要があります。
import * as counterReducers from './counterReducers'; import * as Redux from 'redux'; import * as ReactRouterRedux from 'react-router-redux'; import Counter from '../models/Counter'; export interface AppState { counter: Counter } export const reducer = Redux.combineReducers({ counter: counterReducers.reducer, routing: ReactRouterRedux.routeReducer });
middlewareの設定
続けて、何か拡張的なことやるならお約束のmiddlewareを設定します。 syncHisotryにアプリで使うhistoryを渡してやればmiddlewareが出来上がるのでapplyMiddlewareしてやればOKです。
import * as Redux from 'redux'; import * as ReactDOM from 'react-dom'; import * as React from 'react'; import {Router, Route, IndexRoute} from 'react-router'; import * as ReactRouterRedux from 'react-router-redux'; import {Provider} from 'react-redux'; import App from './components/App'; import IndexPage from './components/IndexPage'; import NextPage from './components/NextPage'; import * as history from 'history'; import * as reducers from './reducers'; const browserHistory = history.createHashHistory(); const createStoreWithMiddleware = Redux.applyMiddleware(ReactRouterRedux.syncHistory(browserHistory))(Redux.createStore); const store = createStoreWithMiddleware(reducers.reducer); const router = ( <Router history={browserHistory}> <Route path='/' component={App}> <IndexRoute component={IndexPage} /> <Route path='/next' component={NextPage} /> </Route> </Router> ); ReactDOM.render( <Provider store={store}> {router} </Provider>, document.getElementById('content'));
画面遷移
画面遷移用のアクションが定義されています。
push, goBack, goFowardあたりを覚えておけばよさそうです。使い方は普通のアクションと同じで、dispatch(ReactRouterRedux.push('/pathtopage'));のようにするかconnectの第二引数でマッピングしてやるかしてやればOKです。
ボタンを押したら/nextというページにパラメータ渡して遷移するような感じのコードは以下のようになります。
import * as React from 'react'; import * as ReactRouter from 'react-router'; import * as ReactRedux from 'react-redux'; import * as reducers from '../reducers'; import * as ReactRouterRedux from 'react-router-redux'; import * as counterActions from '../actions/counterActions'; interface IndexPageProps extends ReactRouter.RouteComponentProps<{}, {}> { push?: ReactRouterRedux.PushAction; increment?: (x: number) => void; decrement?: (x: number) => void; count?: number; } class IndexPage extends React.Component<IndexPageProps, {}> { render() { const { count, increment, decrement, push } = this.props; return ( <div> <span>{count}</span> <br /> <button onClick={() => increment(1)}>INC</button> <button onClick={() => decrement(1)}>DEC</button> <hr /> <button onClick={() => push('/next?count=' + count)}>Go to next page</button> </div> ); } } function select(state: reducers.AppState): IndexPageProps { return { count: state.counter.count }; } export default ReactRedux.connect(select, { push: ReactRouterRedux.push, increment: counterActions.increment, decrement: counterActions.decrement })(IndexPage);
コード全体
コード全体はGitHubに上げています。