Daniel Kidd Tech

27 August 2022, 15:08

Next JS Hydration Issues

In the past I was working on a NextJS site and after some time I have noticed some console errors being logged referring to NextJS hydration issues. This did not have any detrimental effect on the site, but I thought it was worth some investigation.

Initial Error

The console error being logged was not very detailed:

NextJS hydration error

The link that is provided in the error shows the following detail:

NextJS hydration error

So what is this error telling us? Something is changing value between the server rendering the item, and then the item being displayed to the client. My initial thoughts were that it could be related to the auth part of the site, as if a user is logged in their name displays in the header.

This error was not visible when I was developing locally, so it was specific to the production environment… I needed more information.

Investigation

To allow me to resolve the issue I needed to see exactly what content was not matching. The simplest way for me to do that was to change the production environment to build the site in development mode. This may be different depending on the hosting provider but all I had to do was change the YAML file to run yarn dev instead of yarn start.

When I did this I got the following detailed console error:

NextJS hydration error

Ah! The issue is time zone related, as the server defaults to UTC and the machine I am viewing the website on is set to GMT.

Possible Resolutions

Attempt 1

My first thought on fixing the issue was to explicitly set the time zone of the server to GMT. I could easily do this by setting the Node environment variable TZ to the GMT value of Europe/London.

Although this would fix my issue, it would not fix the issue for anybody viewing the website from a different time zone.

Attempt 2

My second idea was to disable Server-Side rendering for the date/time sections in the site as this would be a global fix for everybody.

I was using moment to render the date/time, which looked like:

{moment(props.article.created).format('dddd Do MMMM YYYY HH:MM ')} 

To allow me to disable Server-Side rendering I changed to using the react-moment component <Moment>. I imported it as follows:

const Moment = dynamic(() => import('react-moment'), {
  ssr: false
})

This then allowed me to render the date/time section on the client-side only:

<Moment 
    format='dddd Do MMMM YYYY HH:MM ' 
    date={props.article.created} 
/>

This resolved all hydration / mismatch related issues.