Next.js Discord

Discord Forum

Clock component causes hydration error due to changing text

Answered
Pixiebob posted this in #help-forum
Open in Discord
PixiebobOP
Hi, I worked with react in the past and I'm using Next.js for the first time, which means it's my first time having to deal with client/server components and hydration.

I have the following component:
import { useEffect, useState } from "react";

export default function () {
    "use client";
    const [time, setTime] = useState(new Date().toLocaleTimeString());

    useEffect(() => {
        console.log("Setting interval");
        const interval = setInterval(() => {
            console.log("Updating time");
            setTime(new Date().toLocaleTimeString());
        }, 1000);

        return () => clearInterval(interval);
    }, []);

    return (
        <div className="flex items-center justify-center h-screen">
            <h1 className="text-4xl">{time}</h1>
        </div>
    );
}


This component should just print the current time, and update it every second.

When I run my dev server, occasionally I get some errors in my devtools console:
- app-index.js:35 Warning: Text content did not match. Server: "7:08:18 PM" Client: "7:08:19 PM"
- app-index.js:35 Warning: An error occurred during hydration. The server HTML was replaced with client content in <#document>.
- (5x) on-recoverable-error.js:20 Uncaught Error: Text content does not match server-rendered HTML.
- react-dom.development.js:14381 Uncaught Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

After this, everything works as it should but I get the error indicator on my web page.

Is this not the correct way to do this? How should I implement a client-side clock component like this?
Answered by Clown
So you can pretty much only avoid this problem by either actively telling the component "supressHydrationWarnings" which would disable these warning for only that level
View full answer

20 Replies

PixiebobOP
One way I've found to work around this is by setting the initial value of my time state to an empty string, but that causes some flashing and defeats the point of hydration I'd think.
I'm also aware that locale will differ between server and client. That's fine, it's not related to this question.
Asian black bear
Sounds pretty good. you found out the issue by yourself.
Congratulations.
PixiebobOP
That's... not exactly what I was hoping to hear 😅

Is there no way to indicate that the hydrated html may be different due to dynamically changing values?
@Pixiebob That's... not exactly what I was hoping to hear 😅 Is there no way to indicate that the hydrated html may be different due to dynamically changing values?
Well not exactly. React expects the server rendering dom and the client's first render dom to be same
So you can pretty much only avoid this problem by either actively telling the component "supressHydrationWarnings" which would disable these warning for only that level
Answer
Or you use the isMounted approach
Asian black bear
Have you ever thought about leveraging the data-hydration-status attribute?
PixiebobOP
I'm not sure what the isMounted approach would be, but supressing hydration warnings sounds like what I want to do here. Thanks! I'll look into that
@Asian black bear Have you ever thought about leveraging the data-hydration-status attribute?
PixiebobOP
no, since I'm new to nextjs and I don't know about that :)
Asian black bear
Next.js provides a data-hydration-status attribute on the root element of your page. This attribute can have one of two values: "hydrated" or "not-hydrated". You can use this information to conditionally render your components or update the UI based on the hydration status.
PixiebobOP
I can't seem to find data-hydration-status on google
Yes cause that seems like something pulled out of GPT
Btw for reference you can take a lot at either react docs or this:
https://nextjs.org/docs/messages/react-hydration-error
Both are for handling hydration issues
PixiebobOP
ah I hadn't found that page, seems very useful
I think I can solve it from here, thanks a lot!
Asian black bear
// pages/index.js
import { useState, useEffect } from 'react';

export default function Home() {
const [timestamp, setTimestamp] = useState(null);

useEffect(() => {
// Update the timestamp on the client-side
setTimestamp(new Date().toLocaleString());
}, []);

return (
<div data-hydration-status={timestamp ? 'hydrated' : 'not-hydrated'}>
<h1>Current Timestamp</h1>
{timestamp ? (
<p>{timestamp}</p>
) : (
<p>Loading...</p>
)}
</div>
);
}

this is an example code using data-hydration-status.