reduxを試してみた(4日目) - redux-react-routerを試す

  • 49
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

React.jsと組み合わせるfluxのライブラリreduxを試してみた。 このページは作業ログです。やったことをつらつら書くだけなのでまとめません。あしからず。

対象読者

  • 主に自分

今日のゴール

redux-react-routerとは?

Reactのラウター(ルーターではない)ライブラリとしてよくreact-routerが使われる。react-routerの機能は十分だが、現在表示しているページという"状態"がアプリケーションに登場する。これもできればstoreに押し込めたい。ということで登場したライブラリ。react-routerをベースにしたライブラリなので、まずreact-routerから見ていく。

react-routerの特徴

ドキュメントの構造とURLの構造をマッピングするライブラリ。最初ドキュメントを読んだ時理解できなかったけどこんなことらしい。端的に言えば、画面上のコンポーネントをURLによって切り替えたい部分毎に<Route>を用意し、対応するcomponentを下記のように定義しておくと、URLがマッチする時にコンポーネントを切り替えてくれる。Routeの定義は下記のようになるだろう。

<Route path="/" component="App">
  <IndexRoute component="Home">
  <Route path="home" component="Home"/>
  <Route path="profile" component="Profile"/>
</Route>

<IndexRoute>とは、親のコンポーネントに指定したURLにアクセスしたらレンダリングしたいデフォルトのコンポーネントを指定するためのタグである。上記の例では/にアクセスするとAppHomeがレンダリングされる。それぞれのコンポーネントが下記のように定義されていたとしよう。

App.js
import {Component} from 'react';
import {TopMenu} from '../components/TopMenu';

class App extends Component {
  render() {
    return (
      <div>
        <TopMenu />
        {this.props.children}
      </div>
    );
  }
}
Home.js
import {Component} from 'react';

class Home extends Component {
  render() {
    return (
      <div>
        <H2>Home</H2>
        <section>ここはHomeだよ。</section>
        {this.props.children}
      </div>
    );
  }
}
Profile.js
import {Component} from 'react';

class Profile extends Component {
  render() {
    return (
      <div>
        <H2>Profile</H2>
        <section>ここはProfileだよ。</section>
        {this.props.children}
      </div>
    );
  }
}

/もしくは/homeにアクセスすると、Routeの指定により、下記の構造でレンダリングされる。

<App>
  <Home />
</App>

/profileにアクセスしたとすると、下記のように切り替わる。

<App>
  <Profile />
</App>

切り替えを行うリンクを作成するのは、<Link>である。下記のように利用する。

import {Link} from 'react-router';

...
<Link to='/home'>Home</Link>

例題:現在開いているURLをページ上に出す

画面が遷移できるようになってきたので、試しにURLの変更をUI上に出してみる。下記のように、@connect()でstateの変更を拾えばOK。

Root.js
 @connect(state => ({ routerState: state.router,
   currentLocation : state.router.location.pathname
 }))
 class Root extends Component {
   render() {
     const {currentLocation,children} = this.props;
     return (
       <div>
         <TopMenu/>
         <div className="page-header">
           <h1>{currentLocation}</h1>
         </div>
         {children}
         </div>
       </div>
     );
   }
 }

下記の3行がデータバインディング的な箇所。

 @connect(state => ({ routerState: state.router,
   currentLocation : state.router.location.pathname
 }))

redux-devtoolsを入れておくと、現在のstateの構造がわかるから、それを見て必要そうな状態を拾い上げる。

参考URL