I wrote this post a few days ago in Japanese as well.
The post in Japanese is here.
Overview and Notes
This article describes how to reference the cookie value in _document.js
of Next.js.
Since the code is basically written in TypeScript, the file name may be written as _document.tsx
instead of _document.js
from now on, but it is assumed to be the same file in both cases.
There may not be many cases where you want to refer to the cookie value in _document.js
, But for example, there are cases where you want to control loading scripts in <head>
tags by looking at the cookie value.
(For example, you may want to enable or disable Google Analytics.)
First of all, there are a few things to keep in mind.
First, the way we write here is workaround.
That's because I don't think it's a feature provided on the Next.js side.
(Because looking at the behavior of Next.js, it's hard to discern if this is a pre-expected method.)
So if you can avoid using this method, it's better.
I'm looking into it myself to see if there is a more straightforward method.
Next, I need to run the getServerSideProps
process, which is provided in Next.js as a way to achieve what we want to achieve this time.
So if you're hosting your site as a static site on Nelify
, for example, you can't use getServerSideProps
, so you can't use this approach.
(I haven't checked if there is an alternative.)
Note (About version of Next.js)
As I mentioned earlier, I'm not sure if this is what Next.js is supposed to do or not, so I'll add the possibility that the behavior may change depending on the Next.js version.
This code is verified with version "9.5.5"
.
Reference the cookie value in _document.js in Next.js
First, I wrote the code for verification.
If you want to see the actual behavior, clone this code locally and run it.
Next.js sample of get cookie value at document.tsx
The above code shows how to refer to the cookie value in _document.js.
- Set up the
getServerSideProps
function in the page you want to call (such aspages/index.tsx
).- You don't need to write a process. ->
getServerSideProps
is written only because we want to run it once when drawing the page.
- You don't need to write a process. ->
- Referencing the cookie value from
ctx.req.headers.cookie
in_document.js
Here's the code that actually references the cookie value in _document.tsx
.
Here's a snippet of code from the repository above.
export default class MyDocument extends Document<Props> {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
let hasCookie: boolean = false;
if (ctx.req && ctx.req.headers.cookie) {
console.log('cookie values: ', ctx.req.headers.cookie);
hasCookie = true;
}
return { ...initialProps, hasCookie };
}
render() {
console.log('hasCookie: ', this.props.hasCookie);
I didn't seem to have getServerSideProps
implemented in _document.tsx
, so I used getInitialProps
to get the value of the cookie once.
However, even if this code actually contains the value of the cookie, it doesn't necessarily contain the value in ctx.req.headers.cookie
.
The getServerSideProps
call works in pages/index.tsx
, but if you comment out this code, you won't be able to see the cookie in the above _document.tsx
.
diff --git a/pages/index.tsx b/pages/index.tsx
index 99ea97d..23a6337 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -12,9 +12,11 @@ const IndexPage: React.FC = (): JSX.Element => (
</div>
);
+/*
export async function getServerSideProps() {
console.log('----------> Call getServerSideProps');
return { props: {} };
}
+*/
Specifically, the ctx.req
will be undefined
.
Apparently, only after getServerSideProps
works, the value is stored in ctx.req
in _document.tsx
.
I think this code in Next.js may be helpful for this kind of behavior.
(Sorry if I got it wrong!)
After getServerSideProps
runs, the values are put into ctx.req
.
So now we need to refer to those values (in this case, ctx.req
) on the document side after running it once on the server side.
If anyone knows of a better way to do this, please comment.
Thanks for reading!
Latest comments (2)
I am getting this error
Property 'hasCookie' does not exist on type 'Readonly>[] | ReactFragment | undefined; } & HtmlProps>'.
Thanks for your comment. Sorry it took me so long to reply.
Since my post, the version of Next.js has also been updated, so it is possible that it no longer works with the current version.
If you don't mind, would it be possible for you to provide us with the details of the error?
It would be easier for us to investigate if you include the version of Next.js and Node.js and etc.