I have a Next/React component that is a timer, that starts with the new Date() time when the user arrives to the component. It then resets after the timer gets to 0, starting the countdown of the next hour. I am getting an error from Next.js and I am not sure how to address it as I am using the suggested useEffect and useState provided in the error console.
Error: Warning: Text content did not match. Server: "34" Client: "33"
Error: Uncaught Error: Hydration failed because the initial UI does not match what was rendered on the server.
import { useState, useEffect } from 'react';
import styles from '../styles/App.module.css';
const Timer = () => {
const now: Array<string> = new Date().toISOString()
.split('.')[0]
.split(':')
const nowMin: number = parseInt(now[1]) * 60000,
nowSec: number = parseInt(now[2]) * 1000,
hour: number = 3600000, // one hour in milliseconds
startTime: number = hour - (nowMin + nowSec),
time: number = hour
const [counter, setCounter] = useState(startTime)
useEffect(() => {
const timer = counter > 0 &&
setInterval(() => {
setCounter(counter - 1000)
}, 1000)
return () => clearInterval(timer as any)
}, [counter])
if (counter === 0) {
setCounter(time)
}
return (
<div className={styles.timer}>
<span className={`${styles.code} ${styles.minutes}`}>
{
String(Math.floor((counter % (1000 * 60 * 60)) / (1000 * 60)))
.padStart(2, '0')
}
</span>
<span className={styles.colon}>:</span>
<span className={`${styles.code} ${styles.seconds}`}>
{
String(Math.floor((counter % (1000 * 60)) / 1000))
.padStart(2, '0')
}
</span>
</div>
)
}
export default Timer
I found a solution. You can disable server side rendering in Next.js. On the component importing the Timer component, disabling ssr removed that error. I hope this helps anyone else that is running into the react hydration error:
const Timer = dynamic(() => import('../components/timer'), {
ssr: false
})
...
<Timer />
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