Turn the default Document component into a class component (vercel/turbo#512)

Some code in userland can expect Document to be a class, and as such try to extend it. Extending a function will result in an invalid React component, so it must be a class component.

e.g. https://nextjs.org/docs/advanced-features/custom-document#typescript
This commit is contained in:
Alex Kirszenberg 2022-10-12 12:18:01 +02:00 committed by LongYinan
parent 1d46acd4d4
commit 0527d39665
2 changed files with 25 additions and 11 deletions

View file

@ -67,7 +67,12 @@ async function operation(renderData) {
const initialProps = await loadGetInitialProps(App, {
Component,
// TODO(alexkirsz) Pass in `context`
ctx: {},
ctx: {
// This is necessary for the default Document.getInitialProps to work.
defaultGetInitialProps: async (docCtx, options = {}) => {
return {};
},
},
});
const props = { ...initialProps, ...data.props, pageProps: { ...initialProps.pageProps, ...data.props } };

View file

@ -8,6 +8,7 @@ export function Html(props) {
return <html {...props} />;
}
// TODO(alexkirsz) This should be a class component.
export function Head({ children, ...props }) {
const { styles, scripts } = React.useContext(HtmlContext);
@ -41,6 +42,7 @@ export function htmlEscapeJsonString(str) {
return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
}
// TODO(alexkirsz) This should be a class component.
export function NextScript() {
const { scripts, __NEXT_DATA__ } = React.useContext(HtmlContext);
@ -66,14 +68,21 @@ export function Main() {
return <next-js-internal-body-render-target />;
}
export default function Document() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
// This *must* be a class component, because it can be extended in user code.
export default class Document extends React.Component {
static getInitialProps(ctx) {
return ctx.defaultGetInitialProps(ctx);
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}