-
Notifications
You must be signed in to change notification settings - Fork 27.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose app.js #4129
Expose app.js #4129
Changes from 10 commits
e24d861
d01623f
6eb23be
7c9a422
407f067
1ac18ca
8c1d25c
a87e37f
ffcc795
97ca475
3bec435
1e7cde8
3ac230a
b7bbee2
f126dfb
30089b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('./dist/lib/app') |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Url is deprecated | ||
|
||
#### Why This Error Occurred | ||
|
||
In version prior to 6.x `url` got magically injected into every page component, since this is confusing and can now be added by the user using a custom `_app.js` we have deprecated this feature. To be removed in Next.js 7.0 | ||
|
||
#### Possible Ways to Fix It | ||
|
||
The easiest way to get the same values that `url` had is to use `withRouter`: | ||
|
||
```js | ||
import { withRouter } from 'next/router' | ||
|
||
class Page extends React.Component { | ||
render() { | ||
const {router} = this.props | ||
console.log(router) | ||
return <div>{router.pathname}</div> | ||
} | ||
} | ||
|
||
export default withRouter(Page) | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,34 @@ | ||
import React, { Component } from 'react' | ||
import PropTypes from 'prop-types' | ||
import shallowEquals from './shallow-equals' | ||
import { warn } from './utils' | ||
import { execOnce, warn, loadGetInitialProps } from './utils' | ||
import { makePublicRouterInstance } from './router' | ||
|
||
export default class App extends Component { | ||
state = { | ||
hasError: null | ||
} | ||
|
||
static displayName = 'App' | ||
|
||
static async getInitialProps ({ Component, router, ctx }) { | ||
const pageProps = await loadGetInitialProps(Component, ctx) | ||
return {pageProps} | ||
} | ||
|
||
static childContextTypes = { | ||
_containerProps: PropTypes.any, | ||
headManager: PropTypes.object, | ||
router: PropTypes.object | ||
} | ||
|
||
getChildContext () { | ||
const { headManager } = this.props | ||
const {hasError} = this.state | ||
return { | ||
headManager, | ||
router: makePublicRouterInstance(this.props.router) | ||
router: makePublicRouterInstance(this.props.router), | ||
_containerProps: {...this.props, hasError} | ||
} | ||
} | ||
|
||
|
@@ -29,22 +39,19 @@ export default class App extends Component { | |
} | ||
|
||
render () { | ||
if (this.state.hasError) return null | ||
|
||
const { Component, props, hash, router } = this.props | ||
const {router, Component, pageProps} = this.props | ||
const url = createUrl(router) | ||
// If there no component exported we can't proceed. | ||
// We'll tackle that here. | ||
if (typeof Component !== 'function') { | ||
throw new Error(`The default export is not a React Component in page: "${url.pathname}"`) | ||
} | ||
const containerProps = { Component, props, hash, router, url } | ||
|
||
return <Container {...containerProps} /> | ||
return <Container> | ||
<Component url={url} {...pageProps} /> | ||
</Container> | ||
} | ||
} | ||
|
||
class Container extends Component { | ||
export class Container extends Component { | ||
static contextTypes = { | ||
_containerProps: PropTypes.any | ||
} | ||
|
||
componentDidMount () { | ||
this.scrollToHash() | ||
} | ||
|
@@ -71,10 +78,16 @@ class Container extends Component { | |
} | ||
|
||
render () { | ||
const { Component, props, url } = this.props | ||
const { hasError } = this.context._containerProps | ||
|
||
if (hasError) { | ||
return null | ||
} | ||
|
||
const {children} = this.props | ||
|
||
if (process.env.NODE_ENV === 'production') { | ||
return (<Component {...props} url={url} />) | ||
return <>{children}</> | ||
} else { | ||
const ErrorDebug = require('./error-debug').default | ||
const { AppContainer } = require('react-hot-loader') | ||
|
@@ -83,39 +96,50 @@ class Container extends Component { | |
// https://github.com/gaearon/react-hot-loader/issues/442 | ||
return ( | ||
<AppContainer warnings={false} errorReporter={ErrorDebug}> | ||
<Component {...props} url={url} /> | ||
{children} | ||
</AppContainer> | ||
) | ||
} | ||
} | ||
} | ||
|
||
function createUrl (router) { | ||
const warnUrl = execOnce(() => warn(`Warning: the 'url' property is deprecated. https://err.sh/next.js/url-deprecated`)) | ||
|
||
export function createUrl (router) { | ||
return { | ||
query: router.query, | ||
pathname: router.pathname, | ||
asPath: router.asPath, | ||
get query () { | ||
warnUrl() | ||
return router.query | ||
}, | ||
get pathname () { | ||
warnUrl() | ||
return router.pathname | ||
}, | ||
get asPath () { | ||
warnUrl() | ||
return router.asPath | ||
}, | ||
back: () => { | ||
warn(`Warning: 'url.back()' is deprecated. Use "window.history.back()"`) | ||
warn(`Warning: 'url.back()' is deprecated. Use "window.history.back()" https://err.sh/next.js/url-deprecated`) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't we use something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this was deprecated in v2 or v3. That's what I didn't want to touch it too much, just adding the url to the message. In theory we could use the same message though. Will update it. |
||
router.back() | ||
}, | ||
push: (url, as) => { | ||
warn(`Warning: 'url.push()' is deprecated. Use "next/router" APIs.`) | ||
warn(`Warning: 'url.push()' is deprecated. Use "next/router" APIs. https://err.sh/next.js/url-deprecated`) | ||
return router.push(url, as) | ||
}, | ||
pushTo: (href, as) => { | ||
warn(`Warning: 'url.pushTo()' is deprecated. Use "next/router" APIs.`) | ||
warn(`Warning: 'url.pushTo()' is deprecated. Use "next/router" APIs. https://err.sh/next.js/url-deprecated`) | ||
const pushRoute = as ? href : null | ||
const pushUrl = as || href | ||
|
||
return router.push(pushRoute, pushUrl) | ||
}, | ||
replace: (url, as) => { | ||
warn(`Warning: 'url.replace()' is deprecated. Use "next/router" APIs.`) | ||
warn(`Warning: 'url.replace()' is deprecated. Use "next/router" APIs. https://err.sh/next.js/url-deprecated`) | ||
return router.replace(url, as) | ||
}, | ||
replaceTo: (href, as) => { | ||
warn(`Warning: 'url.replaceTo()' is deprecated. Use "next/router" APIs.`) | ||
warn(`Warning: 'url.replaceTo()' is deprecated. Use "next/router" APIs. https://err.sh/next.js/url-deprecated`) | ||
const replaceRoute = as ? href : null | ||
const replaceUrl = as || href | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('next/app') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If user didn't override
getInitialProps
in his/her sub class, is this going to execute?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep 👍 (Basically the same as
_document.js
that also implementsgetInitialProps