import React, { Component } from 'react' import PropTypes from 'prop-types' import { execOnce, loadGetInitialProps } from './utils' import { makePublicRouterInstance } from './router' export default class App extends Component { static childContextTypes = { headManager: PropTypes.object, router: PropTypes.object } static async getInitialProps ({ Component, router, ctx }) { const pageProps = await loadGetInitialProps(Component, ctx) return {pageProps} } getChildContext () { const { headManager } = this.props return { headManager, router: makePublicRouterInstance(this.props.router) } } // Kept here for backwards compatibility. // When someone ended App they could call `super.componentDidCatch`. This is now deprecated. componentDidCatch (err) { throw err } render () { const {router, Component, pageProps} = this.props const url = createUrl(router) return } } export class Container extends Component { componentDidMount () { this.scrollToHash() } componentDidUpdate () { this.scrollToHash() } scrollToHash () { let { hash } = window.location hash = hash ? hash.substring(1) : false if (!hash) return const el = document.getElementById(hash) if (!el) return // If we call scrollIntoView() in here without a setTimeout // it won't scroll properly. setTimeout(() => el.scrollIntoView(), 0) } render () { return this.props.children } } const warnUrl = execOnce(() => { if (process.env.NODE_ENV !== 'production') { console.error(`Warning: the 'url' property is deprecated. https://err.sh/zeit/next.js/url-deprecated`) } }) export function createUrl (router) { // This is to make sure we don't references the router object at call time const {pathname, asPath, query} = router return { get query () { warnUrl() return query }, get pathname () { warnUrl() return pathname }, get asPath () { warnUrl() return asPath }, back: () => { warnUrl() router.back() }, push: (url, as) => { warnUrl() return router.push(url, as) }, pushTo: (href, as) => { warnUrl() const pushRoute = as ? href : null const pushUrl = as || href return router.push(pushRoute, pushUrl) }, replace: (url, as) => { warnUrl() return router.replace(url, as) }, replaceTo: (href, as) => { warnUrl() const replaceRoute = as ? href : null const replaceUrl = as || href return router.replace(replaceRoute, replaceUrl) } } }