import React, { ErrorInfo } from 'react' import PropTypes from 'prop-types' import { execOnce, loadGetInitialProps, AppContextType, AppInitialProps, AppPropsType, } from 'next-server/dist/lib/utils' import { Router, makePublicRouterInstance } from '../client/router' export { AppInitialProps } export type AppContext = AppContextType export type AppProps

= AppPropsType /** * `App` component is used for initialize of pages. It allows for overwriting and full control of the `page` initialization. * This allows for keeping state between navigation, custom error handling, injecting additional data. */ async function appGetInitialProps({ Component, ctx, }: AppContext): Promise { const pageProps = await loadGetInitialProps(Component, ctx) return { pageProps } } export default class App

extends React.Component< P & AppProps > { static childContextTypes = { router: PropTypes.object, } static origGetInitialProps = appGetInitialProps static getInitialProps = appGetInitialProps getChildContext() { return { router: makePublicRouterInstance(this.props.router), } } // Kept here for backwards compatibility. // When someone ended App they could call `super.componentDidCatch`. // @deprecated This method is no longer needed. Errors are caught at the top level componentDidCatch(error: Error, _errorInfo: ErrorInfo): void { throw error } render() { const { router, Component, pageProps } = this.props as AppProps const url = createUrl(router) return ( ) } } // @deprecated noop for now until removal export function Container(p: any) { return p.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: 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: string, as?: string) => { warnUrl() return router.push(url, as) }, pushTo: (href: string, as?: string) => { warnUrl() const pushRoute = as ? href : '' const pushUrl = as || href return router.push(pushRoute, pushUrl) }, replace: (url: string, as?: string) => { warnUrl() return router.replace(url, as) }, replaceTo: (href: string, as?: string) => { warnUrl() const replaceRoute = as ? href : '' const replaceUrl = as || href return router.replace(replaceRoute, replaceUrl) }, } }