I got most of this code from the official docs example on how to work with styled-components
:
https://github.com/vercel/next.js/blob/canary/examples/with-styled-components/pages/_document.js
But the example uses .js
and I'm using Typescript.
I'm getting some type errors and warning and I'm not sure how to properly type it. I've already solved part of the problem. This is what I'm still missing:
Error 1: What should be the full signature type or the return type for the static async getInitialProps(ctx)
function? What is the type for the ctx
parameter?
Error 2: Unsafe access on ctx.renderPage
. I guess this will be fixed once I properly type the getInitialProps
function
Error 3: This is also probably related to the missing type for getInitialProps
import React, { ReactElement } from "react";
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
render(): ReactElement {
return(
<Html lang="en">
<Head>
// SOMETHING IN THE HEAD
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
getInitialProps is used to asynchronously fetch some data, which then populates props . Data returned from getInitialProps is serialized when server rendering, similar to what JSON.stringify does. Make sure the returned object from getInitialProps is a plain Object and not using Date , Map or Set .
Incremental type checking support added when enabled in your tsconfig.json . Next.js provides an integrated TypeScript experience, including zero-configuration set up and built-in types for Pages, APIs, and more. Clone and deploy the TypeScript starter. View an example application.
To set up a CDN, you can set up an asset prefix and configure your CDN's origin to resolve to the domain that Next. js is hosted on. The exact configuration for uploading your files to a given CDN will depend on your CDN of choice. The only folder you need to host on your CDN is the contents of .
This is what I've ended up doing to type the getInitialProps
and render
methods:
import React, { ReactElement } from "react";
import Document, { DocumentInitialProps, DocumentContext } from 'next/document';
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
// ...
}
render(): ReactElement {
return(
// ...
);
}
}
https://github.com/vercel/next.js/blob/canary/examples/with-styled-components/pages/_document.js
Full styled-components
example:
import React, { ReactElement } from "react";
import Document, { Html, Head, Main, NextScript, DocumentInitialProps, DocumentContext } from 'next/document';
import { ServerStyleSheet } from "styled-components";
// NEXT.JS CUSTOM DOCUMENT
// https://nextjs.org/docs/advanced-features/custom-document
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
render(): ReactElement {
return(
<Html lang="en">
<Head>
// SOME HEAD ELEMENTS
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With