React Routerは何をしているのか？ ~RouterContext編~

## RouterContext

* Routerは必要なmethodやstate, propsなどの値を保持して、RouterContextをrenderする
* 実際に描画されるのはRouterContextである

```js:RouterContext
const RouterContext = React.createClass({
  ...,

  getDefaultProps() {
    return {
      createElement: React.createElement
    }
  },

  ...,

  childContextTypes: {
    history: object,
    location: object.isRequired,
    router: object.isRequired
  },

  getChildContext() {
    let { router, history, location } = this.props
    if (!router) {
      warning(false, '`<RouterContext>` expects a `router` rather than a `history`')

      router = {
        ...history,
        setRouteLeaveHook: history.listenBeforeLeavingRoute
      }
      delete router.listenBeforeLeavingRoute
    }

    if (__DEV__) {
      location = deprecateObjectProperties(location, '`context.location` is deprecated, please use a route component\'s `props.location` instead. http://tiny.cc/router-accessinglocation')
    }

    return { history, location, router }
  },

  ...,

  render() {
    const { history, location, routes, params, components } = this.props
    let element = null

    if (components) {
      element = components.reduceRight((element, components, index) => {
        if (components == null)
          return element // Don't create new children; use the grandchildren.

        const route = routes[index]
        const routeParams = getRouteParams(route, params)
        const props = {
          history,
          location,
          params,
          route,
          routeParams,
          routes
        }

        if (isReactChildren(element)) {
          props.children = element
        } else if (element) {
          for (const prop in element)
            if (Object.prototype.hasOwnProperty.call(element, prop))
              props[prop] = element[prop]
        }

        if (typeof components === 'object') {
          const elements = {}

          for (const key in components) {
            if (Object.prototype.hasOwnProperty.call(components, key)) {
              // Pass through the key as a prop to createElement to allow
              // custom createElement functions to know which named component
              // they're rendering, for e.g. matching up to fetched data.
              elements[key] = this.createElement(components[key], {
                key, ...props
              })
            }
          }

          return elements
        }

        return this.createElement(components, props)
      }, element)
    }

    invariant(
      element === null || element === false || React.isValidElement(element),
      'The root route must render a single element'
    )

    return element
  }

})
```

この4つが組み込みのmethodとなります。
呼ばれる順番は、childContextTypes -> getDefaultProps -> render -> getChildContextとなります。
childContextTypes, getDefaultPropsは値を詰めているだけなので、renderを見に行きます。

```js:render
    const { history, location, routes, params, components } = this.props
```

値が詰められるのは、history, routesとなります。

```js:render
    if (components) {
      ...,
    }
```

この時点でcomponentsはnullのように思えます。
しかし、実はRoute.jsの中でhistory.listenが呼ばれています。
この時点でhistoryのルートURLに対して~~popstate~~pushstateイベントが発生しています。
厳密には、'/'にアクセスすると、サーバはだいたい'index.html'を返すので、そこからjsが読み込まれて、'/'がpushstateされて、setState(state, callback)が呼ばれているようです。
試しに、index.html以外から呼び出すと、何も表示されていませんでした。
index.html以外でも表示されるのかは調査が必要ですね。
なので、一度Router.jsまで遡り、componentsが何なのかを見ていきます。