I am working with dates and Next.js. Below are the three errors I am getting:
Warning: Text content did not match. Server: "Tuesday, January 24, 2023 at 11:01 AM" Client: "Tuesday, January 24, 2023 at 11:01 AM"
Error: Hydration failed because the initial UI does not match what was rendered on the server.
Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
I believe the last two come naturally after the first one.
As you may have noticed, the texts that did not match the server and client are identical. However, I noticed that the space between "11:01" and "AM" is a narrow no-break space (U+202F) for the server and space (U+0020) for the client.
I am using getServerSideProps as described below:
export async function getServerSideProps() {
const eventsResult = (await prisma.event.findMany()).slice(0, 3);
const newsResult = (await prisma.news.findMany()).slice(0, 3);
return {
props: {
events: JSON.parse(JSON.stringify(eventsResult)),
news: JSON.parse(JSON.stringify(newsResult)),
backgroundColor: "red",
},
};
}
At first, I thought it might have something to do with JSON.parse and JSON.stringify. So, I changed it with no luck:
export async function getServerSideProps() {
const eventsResult = (await prisma.event.findMany()).slice(0, 3);
const newsResult = (await prisma.news.findMany()).slice(0, 3);
const formattedEventsResults = eventsResult.map((e) => ({
...e,
start: e.start.toString(),
end: e.start.toString(),
}));
const formattedNewsResult = newsResult.map((n) => ({
...n,
datetime: n.datetime.toString(),
}));
return {
props: {
events: formattedEventsResults,
news: formattedNewsResult,
backgroundColor: "red",
},
};
}
The exact line in the component that displays the date above is:
(I am trying to avoid timezone conversions because all the dates are for a simple project using all fake data. I just need the stored and displayed values to match)
{new Date(props.start).toLocaleString(undefined, {
timeZone: "UTC",
year: "numeric",
month: "long",
day: "2-digit",
weekday: "long",
hour: "2-digit",
minute: "2-digit",
})}
How can I ensure the server and client render the same character and avoid the hydration errors?
I solved this issue by replacing all spaces in the formatted date with a standard space. e.g.
const myFormattedDate = new Date().toLocaleString(undefined, {
timeZone: "UTC",
year: "numeric",
month: "long",
day: "2-digit",
weekday: "long",
hour: "2-digit",
minute: "2-digit",
}).replace(/\s/g, ' ')