Router　React

忘れそうなのでメモ。
ReactのRouterについて
間違えていたらご指摘お願い致します。

参考資料　

CSS-tricks Router
https://css-tricks.com/learning-react-router/

Beginner’s Guide to React Router
https://medium.com/@dabit3/beginner-s-guide-to-react-router-53094349669

```app.js
import React, { Component } from 'react'
import { Router, Route, Link, IndexRoute, hashHistory, browserHistory } from 'react-router'

class App extends Component {
  render() {
    return (
      // More standard which has history don't mix with Link
      // Only Router has history but Route doesnt have history
      // You can put Link inside of Router but don't do that
      <Router history={browserHistory}>
          <Route path='/' component={Home} />
          <Route path='/address' component={Address} />
          <Route path='/name' component={Name} />
          <Route path='/*' component={NotFound} />
      </Router>
    )
  }
}

const Home = () => (
  <div>
    <h1>Hello from Home!</h1>
    <Link to="/address">React Link</Link><br/>
    <a href="/address">Native Link</a><br/>
    <Link to="/name">Name Link</Link><br/>
  </div>
)
const Address = () => <h1>We are located at 555 Jackson St.</h1>
const NotFound = () => (
  <h1>404. Haruna says: This page is not found!</h1>
)
const Name = () => <h1>This is my name </h1>
export default App


// hashihistory : default
// some browser doens't support browserHistory
// browser manage browserHistory
// React manage hashhistory

```

## Router
　Routeを囲んで使う
　Routerはhistoryをもっている
　Routeがhistoryを持っているのではない

##Link
　historyがない
　ページの遷移はない
　でも表示する場所を変更するから、あたかもページが遷移したかのように見える

##IndexLink
  そのリンクを押されたときだけclassをonにしたいと思ったときに、書き方が２パターンある。
１つ目の書き方のほうが便利。

```indexlink_sample.html
// pattern1
<IndexLink to='/' activeClassName='active'>Home</Link>
<Link to='/address'>Address</Link>

// pattern2
<Link to='/' activeClassName='active' onlyActiveOnIndex={true}>Home</Link>
<Link to='/address'>Address</Link>

```

## プロセス

ユーザーがどこかクリックする
クリックされたリンクに移動する
その移動した際のpathがRouterのhistoryにpushされる
pushされたあとに、Routeの一番上から
pathが一致するのがないかチェックする
マッチするのがあれば、そのコンポーネントを返す


## Middleware
リクエストを受け取るフレームワークとレスポンスを作り出すフレームワークの間に挿入するコード。最もよい特徴はチェーンの中に生み出せる。いくつもの独立したMiddlewareをひとつのプロジェクトの中に使うことができる。
このmiddlewareはactionをおくるポイントと、reducerに届くまでの間に設定する。

### 課題１：ログ
Reduxは変更を予想可能で透明性の高いものにできる。
reducerにかけられたobjectは新しいstateを生み出す。
変更される度に新しいstateが生み出される。

### ステップ１：一つ一つマニュアルでログする
変更のあるあらゆるところに
store.dispatch(addTodo('Use Redux'))などをいれる
store: データにアクセスできる
addTodo: データを追加するためのactionCreator
actionCreatorにデータを挿入して、TYPEを追加してstoreに送る。
store.getState()とすると、その時のstateを取得できる。

### ステップ２：ディスパッチをラップする
```manualDispatch.js

function dispatchAndLog(store, action) {
  console.log('dispatching', action)
  store.dispatch(action)
  console.log('next state', store.getState())
}

// then
dispatchAndLog(store, addTodo('Use Redux'))

```

### ステップ３：MonkeyPatching Dispatch

もしdispatchをstoreで置き換えたらどうなるか。

```storeDispatch.js

let next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
  console.log('dispatching', action)
  let result = next(action)
  console.log('next state',  store.getState())
  return result
}

```

### 問題：　クラッシングレポート

ログし続け、クラッシュが起こった際は別の結果を返すようにするのが大切。クラッシュが起こった結果は別のパッケージの別のモデュールにいれる必要がある。そうしないと活用しにくい。

ロギングとクラッシュレポートは分ける。以下のように。

```crashingReport.js

function patchStoreToAddLogging(store) {
	let next = store.dispatch
	store.dispatch = function dispatchAndLog(action) {
		console.log('dispatching', action)
		let result = next(action)
		console.log('next state', store.getState())
		return result
	}
}

function patchStoreToAddCreashReporting(store) {
	let next = store.dispatch
	store.dispatch = function dispatchAndReportErrors(action) {
		try {
			return next(action)
		} catch (err) {
			console.log('Caught an exception!', err)
			Raven.captureException(err, {
				extra: {
					action,
					state: store.getState()
				}
			})
			throw err
		}
	}
}

```

別のモデュールで使いたいと思ったら以下のように書けばOK

```otherModule.js

patchStoreToAddLogging(store)
patchStoreToAddCrashReporting(store)
// NOT NICE

```

###　ステップ４：MonckyPatchingを隠す

ステップ３を書くのはかっこよくないからMonckyPatchingを隠せないか考える。

```hidingMonckyPatching.js

function applyMiddlewareByMonkeypatching (store, middlewares) {
	middlewares = middlewares.slice()
	middlewares.reverse()

	middlewares.forEach(middleware => 
		store.dispatch = middleware(store)
	)
}

// Later
applyMiddlewareByMonkeypatching(store, [logger, crashReporter])

```

### ステップ５：MonckyPatchingを削除する

dispatchをなぜ上書きするのか。
それはあとで呼び出すため。でも、他の理由もある。
それはラップされたstore.dispatchなのだ。
middlewareをチェーンにすることは大切。
もしapplyMiddlewareByMonckypatchingがstore.dispatchをひとつめのmiddlewareを読みこんですぐ配置しなかった場合、いつもstore.dispatchはもともとのdispatchを見てしまう。そうすると２つ目のmiddlewareも最初のdispatchを見てしまう。

別の方法はmiddlewareをネストする。

```removeMonckyPatching.js
function logger(store) {
	return function wrapDisptchToAddLoggin(next) {
		return function dispatchAndLog(action) {
			console.log('dispatching', action)
			let result = next(action)
			console.log('next state', store.getState())
			return result
		}
	}
}

const crashReporter = store => next => action => {
	try {
		return next(action)
	} catch (err) {
		console.error('Caught an exception', err)
		Raven.captureException(err, {
			extra: {
				action,
				state: store.getState()
			}
		})
		throw err
	}
}
```
これのfunctionの名前をapplyMiddleware()にすればほぼ一緒。
でも違う点が３点
1. dispatch(action)とgetState()されたmiddlewareにだけstoreをさらけ出す。
2. store.dispatch(action)を呼ぶと、middlewareのチェーンを再びまたとおる。
3. 一度だけmiddlewareにとおすために、(store, middleware_ => storeではなく、(...middlewares) => (createStore) => createStoreにする