2016-10-05 23:52:50 +00:00
|
|
|
import React, { Component, PropTypes } from 'react'
|
2016-10-14 15:05:08 +00:00
|
|
|
import { AppContainer } from 'react-hot-loader'
|
2017-01-12 01:58:20 +00:00
|
|
|
import shallowEquals from './shallow-equals'
|
2016-12-19 21:04:38 +00:00
|
|
|
import { warn } from './utils'
|
2016-10-05 23:52:50 +00:00
|
|
|
|
2017-01-12 01:58:20 +00:00
|
|
|
const ErrorDebug = process.env.NODE_ENV === 'production'
|
|
|
|
? null : require('./error-debug').default
|
|
|
|
|
2016-10-05 23:52:50 +00:00
|
|
|
export default class App extends Component {
|
|
|
|
static childContextTypes = {
|
|
|
|
headManager: PropTypes.object
|
|
|
|
}
|
|
|
|
|
2017-01-12 01:58:20 +00:00
|
|
|
getChildContext () {
|
|
|
|
const { headManager } = this.props
|
|
|
|
return { headManager }
|
2016-10-05 23:52:50 +00:00
|
|
|
}
|
|
|
|
|
2017-01-12 01:58:20 +00:00
|
|
|
render () {
|
2017-02-28 17:31:17 +00:00
|
|
|
const { Component, props, hash, err, router } = this.props
|
|
|
|
const containerProps = { Component, props, hash, router }
|
2016-10-05 23:52:50 +00:00
|
|
|
|
2017-01-12 01:58:20 +00:00
|
|
|
return <div>
|
|
|
|
<Container {...containerProps} />
|
2017-01-21 18:46:18 +00:00
|
|
|
{ErrorDebug && err ? <ErrorDebug error={err} /> : null}
|
2017-01-12 01:58:20 +00:00
|
|
|
</div>
|
2016-10-05 23:52:50 +00:00
|
|
|
}
|
2017-01-12 01:58:20 +00:00
|
|
|
}
|
2016-10-05 23:52:50 +00:00
|
|
|
|
2017-01-12 01:58:20 +00:00
|
|
|
class Container extends Component {
|
2017-02-28 17:31:17 +00:00
|
|
|
componentDidMount () {
|
|
|
|
this.scrollToHash()
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidUpdate () {
|
|
|
|
this.scrollToHash()
|
|
|
|
}
|
|
|
|
|
|
|
|
scrollToHash () {
|
|
|
|
const { hash } = this.props
|
|
|
|
const el = document.getElementById(hash)
|
|
|
|
if (el) {
|
|
|
|
// If we call scrollIntoView() in here without a setTimeout
|
|
|
|
// it won't scroll properly.
|
|
|
|
setTimeout(() => el.scrollIntoView(), 0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-12 01:58:20 +00:00
|
|
|
shouldComponentUpdate (nextProps) {
|
|
|
|
// need this check not to rerender component which has already thrown an error
|
|
|
|
return !shallowEquals(this.props, nextProps)
|
2016-10-05 23:52:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
render () {
|
2017-01-12 01:58:20 +00:00
|
|
|
const { Component, props, router } = this.props
|
|
|
|
const url = createUrl(router)
|
2016-10-14 15:05:08 +00:00
|
|
|
|
2017-01-12 01:58:20 +00:00
|
|
|
// includes AppContainer which bypasses shouldComponentUpdate method
|
|
|
|
// https://github.com/gaearon/react-hot-loader/issues/442
|
2017-01-21 18:46:18 +00:00
|
|
|
return <AppContainer errorReporter={ErrorDebug}>
|
2017-01-12 01:58:20 +00:00
|
|
|
<Component {...props} url={url} />
|
2016-10-14 15:05:08 +00:00
|
|
|
</AppContainer>
|
2016-10-05 23:52:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-12 01:58:20 +00:00
|
|
|
function createUrl (router) {
|
|
|
|
return {
|
2016-10-05 23:52:50 +00:00
|
|
|
query: router.query,
|
|
|
|
pathname: router.pathname,
|
|
|
|
back: () => router.back(),
|
2016-12-19 18:49:15 +00:00
|
|
|
push: (url, as) => router.push(url, as),
|
2016-12-17 20:18:50 +00:00
|
|
|
pushTo: (href, as) => {
|
2016-12-19 21:04:38 +00:00
|
|
|
warn(`Warning: 'url.pushTo()' is deprecated. Please use 'url.push()' instead.`)
|
2016-12-17 20:18:50 +00:00
|
|
|
const pushRoute = as ? href : null
|
|
|
|
const pushUrl = as || href
|
|
|
|
|
|
|
|
return router.push(pushRoute, pushUrl)
|
|
|
|
},
|
2016-12-19 18:49:15 +00:00
|
|
|
replace: (url, as) => router.replace(url, as),
|
2016-12-17 20:18:50 +00:00
|
|
|
replaceTo: (href, as) => {
|
2016-12-19 21:04:38 +00:00
|
|
|
warn(`Warning: 'url.replaceTo()' is deprecated. Please use 'url.replace()' instead.`)
|
2016-12-17 20:18:50 +00:00
|
|
|
const replaceRoute = as ? href : null
|
|
|
|
const replaceUrl = as || href
|
|
|
|
|
|
|
|
return router.replace(replaceRoute, replaceUrl)
|
|
|
|
}
|
2016-10-05 23:52:50 +00:00
|
|
|
}
|
|
|
|
}
|